Check that hwnd is not null before calling SetSystemTimer or KillSystemTimer in functions ShowCaret, HideCaret and SetCaretPos.
Reason: If there is no caret window, the call in ShowCaret, SetSystemTimer( hwnd, TIMERID, Caret.timeout, CARET_Callback ); will create (and leak) a timer since TIMERID is not used if hwnd is null. Similar issues affect the other functions.
Illustration: Depending on your system (Alt+Tab or Alt+Esc switching between applications), this is seen even in standard applications: (1) Start Notepad.exe. (2) Hold down Alt (do not release). (3) Rick-click to open the context menu. (4) Switch to another application without first returning the focus to the edit field by pressing Tab or Esc. (The context menu should remain open.) (5) Close the context menu while Notepad is not active. Now SetSystemTimer has been called with a null hwnd (via ShowCaret(0) in MENU_ExitTracking() in menu.c) and a timer has been leaked. When you switch back to Notepad, the caret flashes more frequently / irregularly. The patch fixes this.
Signed-off-by: Robert Schlicht patch@rschlicht.eu --- dlls/user32/caret.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-)
diff --git a/dlls/user32/caret.c b/dlls/user32/caret.c index 686dade410..edcbc3cd6b 100644 --- a/dlls/user32/caret.c +++ b/dlls/user32/caret.c @@ -269,7 +269,7 @@ BOOL WINAPI SetCaretPos( INT x, INT y ) } } SERVER_END_REQ; - if (ret && !hidden && (x != r.left || y != r.top)) + if (ret && hwnd && !hidden && (x != r.left || y != r.top)) { if (old_state) CARET_DisplayCaret( hwnd, &r ); r.right += x - r.left; @@ -314,7 +314,7 @@ BOOL WINAPI HideCaret( HWND hwnd ) } SERVER_END_REQ;
- if (ret && !hidden) + if (ret && hwnd && !hidden) { if (old_state) CARET_DisplayCaret( hwnd, &r ); KillSystemTimer( hwnd, TIMERID ); @@ -352,7 +352,7 @@ BOOL WINAPI ShowCaret( HWND hwnd ) } SERVER_END_REQ;
- if (ret && (hidden == 1)) /* hidden was 1 so it's now 0 */ + if (ret && hwnd && (hidden == 1)) /* hidden was 1 so it's now 0 */ { CARET_DisplayCaret( hwnd, &r ); SetSystemTimer( hwnd, TIMERID, Caret.timeout, CARET_Callback );