[PATCH 0/2] RedrawWindow with RDW_VALIDATE
Hello developers, this is the last fix from my recent series of patches that make ConEmu fully usable in wine. It would be great if these could get into Wine. I am ready to improve them eventually, looking forward for your comments. Regards, Roman Roman Pišl (2): user32/tests: Add test for RedrawWindow with RDW_VALIDATE flag. user32/painting: Trigger WM_PAINT before validating in RedrawWindow. dlls/user32/painting.c | 9 ++++++++- dlls/user32/tests/msg.c | 25 ++++++++++++++++++++++++- 2 files changed, 32 insertions(+), 2 deletions(-) -- 2.20.1
Signed-off-by: Roman Pišl <rpisl(a)seznam.cz> --- dlls/user32/tests/msg.c | 26 +++++++++++++++++++++++++- 1 file changed, 25 insertions(+), 1 deletion(-) diff --git a/dlls/user32/tests/msg.c b/dlls/user32/tests/msg.c index 93ab7b4a27..4df10a8300 100644 --- a/dlls/user32/tests/msg.c +++ b/dlls/user32/tests/msg.c @@ -136,7 +136,8 @@ typedef enum { optional=0x80, hook=0x100, winevent_hook=0x200, - kbd_hook=0x400 + kbd_hook=0x400, + has_update=0x800 } msg_flags_t; struct message { @@ -2547,6 +2548,11 @@ static void ok_sequence_(const struct message *expected_list, const char *contex context, count, expected->message); if ((expected->flags & kbd_hook) != (actual->flags & kbd_hook)) dump++; + todo_wine_if(line==8239) + ok_( file, line) (!(expected->flags & has_update) || (actual->flags & has_update), + "%s: %u: the msg 0x%04x should have update region\n", + context, count, expected->message); + expected++; actual++; } @@ -7858,6 +7864,11 @@ static const struct message WmPaint[] = { { 0 } }; +static const struct message WmPaintUpdate[] = { + { WM_PAINT, sent|has_update }, + { 0 } +}; + static const struct message WmParentOnlyPaint[] = { { WM_PAINT, sent|parent }, { 0 } @@ -8217,6 +8228,16 @@ static void test_paint_messages(void) } ok_sequence( WmGetUpdateRect, "GetUpdateRect", FALSE ); + /* RedrawWindow with RDW_VALIDATE triggers WM_PAINT with non-empty update region */ + flush_sequence(); + InvalidateRect( hwnd, NULL, FALSE ); + GetClientRect( hwnd, &rect ); + SetRectRgn(hrgn, rect.left, rect.top, rect.right, rect.bottom ); + check_update_rgn( hwnd, hrgn ); + RedrawWindow( hwnd, &rect, NULL, RDW_INTERNALPAINT|RDW_NOERASE|RDW_NOFRAME|RDW_UPDATENOW|RDW_VALIDATE ); + check_update_rgn( hwnd, 0 ); + ok_sequence( WmPaintUpdate, "PaintUpdate", FALSE ); + DestroyWindow( hwnd ); /* now test with a child window */ @@ -9531,6 +9552,9 @@ static LRESULT MsgCheckProc (BOOL unicode, HWND hwnd, UINT message, msg.flags = sent|wparam|lparam; if (defwndproc_counter) msg.flags |= defwinproc; if (beginpaint_counter) msg.flags |= beginpaint; + + if (message == WM_PAINT && GetUpdateRect(hwnd, NULL, FALSE)) msg.flags |= has_update; + msg.wParam = wParam; msg.lParam = lParam; msg.descr = "MsgCheckProc"; -- 2.20.1
Roman Pišl <rpisl(a)seznam.cz> wrote:
+ /* RedrawWindow with RDW_VALIDATE triggers WM_PAINT with non-empty update region */ + flush_sequence(); + InvalidateRect( hwnd, NULL, FALSE ); + GetClientRect( hwnd, &rect ); + SetRectRgn(hrgn, rect.left, rect.top, rect.right, rect.bottom ); + check_update_rgn( hwnd, hrgn ); + RedrawWindow( hwnd, &rect, NULL, RDW_INTERNALPAINT|RDW_NOERASE|RDW_NOFRAME|RDW_UPDATENOW|RDW_VALIDATE ); + check_update_rgn( hwnd, 0 ); + ok_sequence( WmPaintUpdate, "PaintUpdate", FALSE );
Probably RedrawWindow() should ignore RDW_VALIDATE if RDW_UPDATENOW is also set, did you try that? -- Dmitry.
Dne 22. 04. 20 v 14:31 Dmitry Timoshkov napsal(a):
Roman Pišl <rpisl(a)seznam.cz> wrote:
+ /* RedrawWindow with RDW_VALIDATE triggers WM_PAINT with non-empty update region */ + flush_sequence(); + InvalidateRect( hwnd, NULL, FALSE ); + GetClientRect( hwnd, &rect ); + SetRectRgn(hrgn, rect.left, rect.top, rect.right, rect.bottom ); + check_update_rgn( hwnd, hrgn ); + RedrawWindow( hwnd, &rect, NULL, RDW_INTERNALPAINT|RDW_NOERASE|RDW_NOFRAME|RDW_UPDATENOW|RDW_VALIDATE ); + check_update_rgn( hwnd, 0 ); + ok_sequence( WmPaintUpdate, "PaintUpdate", FALSE );
Probably RedrawWindow() should ignore RDW_VALIDATE if RDW_UPDATENOW is also set, did you try that?
Putting this to beginning of RedrawWindow: + if (flags & RDW_UPDATENOW) + flags &= ~RDW_VALIDATE; breaks test: msg.c:8185: Test failed: Paint: 1: the msg sequence is not complete: expected 0000 - actual 0014 msg.c:8185: Failed sequence Paint: msg.c:8185: 0: expected: msg 000f - actual: MsgCheckProc: 00000000002B0044 000f wp 00000000 lp 00000000 (flags 819) msg.c:8185: 1: expected: nothing - actual: MsgCheckProc: 00000000002B0044 0014 wp 00160042 lp 00000000 (flags 59) Putting this: + if ((flags & (RDW_UPDATENOW | RDW_INTERNALPAINT)) == (RDW_UPDATENOW | RDW_INTERNALPAINT)) + flags &= ~RDW_VALIDATE; Breaks no test and also fixes the issue. Seems like a better solution so far.
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=70265 Your paranoid android. === w8adm (32 bit report) === user32: msg.c:17646: Test failed: wrong status 00080000 === w1064v1809 (32 bit report) === user32: msg.c:8810: Test failed: MsgWaitForMultipleObjects failed 102 === w1064v1809_he (32 bit report) === user32: msg.c:8810: Test failed: MsgWaitForMultipleObjects failed 102
Wine-Bug: https://bugs.winehq.org/show_bug.cgi?id=48761 Signed-off-by: Roman Pišl <rpisl(a)seznam.cz> --- dlls/user32/painting.c | 9 ++++++++- dlls/user32/tests/msg.c | 1 - 2 files changed, 8 insertions(+), 2 deletions(-) diff --git a/dlls/user32/painting.c b/dlls/user32/painting.c index 313c5fa1e6..d91305a714 100644 --- a/dlls/user32/painting.c +++ b/dlls/user32/painting.c @@ -1229,6 +1229,7 @@ BOOL WINAPI RedrawWindow( HWND hwnd, const RECT *rect, HRGN hrgn, UINT flags ) { static const RECT empty; BOOL ret; + BOOL updated = FALSE; if (TRACE_ON(win)) { @@ -1249,6 +1250,12 @@ BOOL WINAPI RedrawWindow( HWND hwnd, const RECT *rect, HRGN hrgn, UINT flags ) /* process pending expose events before painting */ if (flags & RDW_UPDATENOW) USER_Driver->pMsgWaitForMultipleObjectsEx( 0, NULL, 0, QS_PAINT, 0 ); + if ((flags & (RDW_INTERNALPAINT | RDW_UPDATENOW | RDW_VALIDATE)) == (RDW_INTERNALPAINT | RDW_UPDATENOW | RDW_VALIDATE)) + { + update_now( hwnd, flags ); + updated = TRUE; + } + if (rect && !hrgn) { if (IsRectEmpty( rect )) rect = ∅ @@ -1275,7 +1282,7 @@ BOOL WINAPI RedrawWindow( HWND hwnd, const RECT *rect, HRGN hrgn, UINT flags ) if (!hwnd) hwnd = GetDesktopWindow(); - if (flags & RDW_UPDATENOW) update_now( hwnd, flags ); + if (flags & RDW_UPDATENOW && !updated) update_now( hwnd, flags ); else if (flags & RDW_ERASENOW) erase_now( hwnd, flags ); return ret; diff --git a/dlls/user32/tests/msg.c b/dlls/user32/tests/msg.c index 4df10a8300..3a0dd8dbbb 100644 --- a/dlls/user32/tests/msg.c +++ b/dlls/user32/tests/msg.c @@ -2548,7 +2548,6 @@ static void ok_sequence_(const struct message *expected_list, const char *contex context, count, expected->message); if ((expected->flags & kbd_hook) != (actual->flags & kbd_hook)) dump++; - todo_wine_if(line==8239) ok_( file, line) (!(expected->flags & has_update) || (actual->flags & has_update), "%s: %u: the msg 0x%04x should have update region\n", context, count, expected->message); -- 2.20.1
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=70266 Your paranoid android. === wxppro (32 bit report) === user32: msg.c:17040: Test failed: SetFocus on a child window: 4: the msg 0x001c was expected, but got msg 0x0047 instead
I see no way how could it be related to the change. Dne 22. 04. 20 v 15:02 Marvin napsal(a):
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=70266
Your paranoid android.
=== wxppro (32 bit report) ===
user32: msg.c:17040: Test failed: SetFocus on a child window: 4: the msg 0x001c was expected, but got msg 0x0047 instead
participants (3)
-
Dmitry Timoshkov -
Marvin -
Roman Pišl