Fix mouse cursor flicker while hovering

The reason, why the flicker occurs, is the following: There are two Windows messages sent by Windows to Scintilla, when the mouse is moved: WM_MOUSEMOVE and WM_SETCURSOR.

WM_MOUSEMOVE informs Scintilla, that the mouse has been moved inside its window.
WM_SETCURSOR informs Scintilla, that the mouse cursor has been moved. Anywhere, not necessarily in its window.
Scintilla calls the Windows function SetCursor (, which sets the mouse cursor shape, not the position), while processing both messages. Unfortunately, Scintilla uses different ways to calculate the desired cursor shape. So, whenever the mouse cursor is moved, two SetCursor calls are applied, sometimes with two different cursor shapes.

On WM_MOUSEMOVE, Scintilla calls ButtonMoveWithModifiers, which sets the correct cursor shape.
On WM_SETCURSOR, Scintilla calls SetCursor directly, sometimes with the wrong cursor shape.

This PR shows how to eliminate this effect in the modified Scintilla version used by Notepad++. This may be the fastest way to get results without introducing new effects.

The current original Scintilla version (Version 4.4.4, downloaded 2020-07-30, 5d134721c303ceecbdcb28ec82b28f0cbbdb4a55) has the same effect and can be fixed in the same way, although the WM_SETCURSOR code has been changed a little. Before updating to a new Scintilla version, we should try to get it fixed in the original Scintilla.

Fix #8588, fix #8647, close #8641
This commit is contained in:
Udo Hoffmann 2020-07-30 17:04:33 +02:00 committed by Don HO
parent c119dd41a2
commit d55350b4b5
No known key found for this signature in database
GPG Key ID: 6C429F1D8D84F46E
2 changed files with 42 additions and 2 deletions

View File

@ -4486,6 +4486,12 @@ void Editor::DwellEnd(bool mouseMoved) {
void Editor::MouseLeave() {
SetHotSpotRange(nullptr);
// Fix the following issue:
// #8647
// It could be fixed in Scintilla release superior to v4.4.4 - to verify.
// ++ added
SetHoverIndicatorPosition(INVALID_POSITION);
// -- added
if (!HaveMouseCapture()) {
ptMouseLast = Point(-1, -1);
DwellEnd(true);
@ -4675,6 +4681,12 @@ void Editor::ButtonDownWithModifiers(Point pt, unsigned int curTime, int modifie
lastClick = pt;
lastXChosen = static_cast<int>(pt.x) + xOffset;
ShowCaretAtCurrentPosition();
// Fix the following issue:
// #8647
// It could be fixed in Scintilla release superior to v4.4.4 - to verify.
// ++ added
if (inSelMargin) SetHoverIndicatorPosition(INVALID_POSITION);
// -- added
}
void Editor::RightButtonDownWithModifiers(Point pt, unsigned int, int modifiers) {
@ -4848,18 +4860,37 @@ void Editor::ButtonMoveWithModifiers(Point pt, unsigned int, int modifiers) {
}
hotSpotClickPos = INVALID_POSITION;
}
// Fix the following issue:
// #8647
// It could be fixed in Scintilla release superior to v4.4.4 - to verify.
// ++ added
if ((vs.fixedColumnWidth > 0) && PointInSelMargin(pt)) {
SetHoverIndicatorPosition(INVALID_POSITION);
}
// -- added
} else {
if (vs.fixedColumnWidth > 0) { // There is a margin
if (PointInSelMargin(pt)) {
DisplayCursor(GetMarginCursor(pt));
SetHotSpotRange(nullptr);
// Fix the following issue:
// #8647
// It could be fixed in Scintilla release superior to v4.4.4 - to verify.
// ++ added
SetHoverIndicatorPosition(INVALID_POSITION);
// -- added
return; // No need to test for selection
}
}
// Display regular (drag) cursor over selection
if (PointInSelection(pt) && !SelectionEmpty()) {
DisplayCursor(Window::cursorArrow);
// Fix the following issue:
// #8647
// It could be fixed in Scintilla release superior to v4.4.4 - to verify.
// ++ added
SetHoverIndicatorPosition(INVALID_POSITION);
// -- added
} else {
SetHoverIndicatorPoint(pt);
if (PointIsHotspot(pt)) {

View File

@ -1463,7 +1463,16 @@ sptr_t ScintillaWin::WndProc(unsigned int iMessage, uptr_t wParam, sptr_t lParam
} else if (PointIsHotspot(PointFromPOINT(pt))) {
DisplayCursor(Window::cursorHand);
} else {
DisplayCursor(Window::cursorText);
// Fix the following issue:
// #8588
// It should be fixed in Scintilla release superior to v4.4.4 - to verify.
// ++ added
Sci::Position pos = PositionFromLocation(PointFromPOINT(pt), true, true);
if ((pos != INVALID_POSITION) && (hoverIndicatorPos != Sci::invalidPosition))
DisplayCursor(Window::cursorHand);
else
// -- added
DisplayCursor(Window::cursorText);
}
}
}