From d55350b4b5db71889d0a92aabe5ae10d41c92507 Mon Sep 17 00:00:00 2001 From: Udo Hoffmann Date: Thu, 30 Jul 2020 17:04:33 +0200 Subject: [PATCH] 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 --- scintilla/src/Editor.cxx | 33 +++++++++++++++++++++++++++++++- scintilla/win32/ScintillaWin.cxx | 11 ++++++++++- 2 files changed, 42 insertions(+), 2 deletions(-) diff --git a/scintilla/src/Editor.cxx b/scintilla/src/Editor.cxx index d6593ea2..f9de3103 100644 --- a/scintilla/src/Editor.cxx +++ b/scintilla/src/Editor.cxx @@ -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(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)) { diff --git a/scintilla/win32/ScintillaWin.cxx b/scintilla/win32/ScintillaWin.cxx index 8c0b6e5c..92e64d44 100644 --- a/scintilla/win32/ScintillaWin.cxx +++ b/scintilla/win32/ScintillaWin.cxx @@ -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); } } }