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 );
Hi,
While running your changed tests, I think I found new failures. Being a bot and all I'm not very good at pattern recognition, so I might be wrong, but could you please double-check?
Full results can be found at: https://testbot.winehq.org/JobDetails.pl?Key=65200
Your paranoid android.
=== debian10 (32 bit Chinese:China report) ===
user32: msg.c:17559: Test succeeded inside todo block: WaitForSingleObject failed, ret:0 msg.c:17569: Test failed: wrong status 00080000 msg.c:17583: Test succeeded inside todo block: wrong status 00000000 msg.c:17587: Test succeeded inside todo block: SendMessage from other thread 5: marked "todo_wine" but succeeds