This is confirmed by the tests in test_scrollbar() and manual tests on XP. Even though scrollbar arrows and thumb are in fact transparent, DrawThemeParentBackground() is not called to paint the parent background, leaving the transparent area untouched. On Windows, even if the scrollbar arrows are reported to be transparent, the bitmaps for arrow parts in the stock themes are in fact opaque.
Fix Ice Cream Calculator slow scrolling after 4cb229a because the WM_PRINTCLIENT handling in the application is slow.
From: Zhiyi Zhang zzhang@codeweavers.com
--- dlls/uxtheme/tests/system.c | 140 ++++++++++++++++++++++++++++++++++++ 1 file changed, 140 insertions(+)
diff --git a/dlls/uxtheme/tests/system.c b/dlls/uxtheme/tests/system.c index debc712a73c..f0f51a68009 100644 --- a/dlls/uxtheme/tests/system.c +++ b/dlls/uxtheme/tests/system.c @@ -2550,6 +2550,144 @@ static void test_GetThemeBackgroundRegion(void) DestroyWindow(hwnd); }
+static const struct message wm_ctlcolorscrollbar_seq[] = +{ + {WM_CTLCOLORSCROLLBAR, sent}, + {WM_CTLCOLORSCROLLBAR, sent | optional}, + {0} +}; + +static LRESULT WINAPI TestScrollBarParentProcA(HWND hwnd, UINT msg, WPARAM wp, LPARAM lp) +{ + static LONG defwndproc_counter; + static HBRUSH red_brush; + struct message message = {0}; + LRESULT ret; + + message.message = msg; + message.flags = sent | wparam | lparam; + if (defwndproc_counter) + message.flags |= defwinproc; + message.wParam = wp; + message.lParam = lp; + add_message(sequences, PARENT_SEQ_INDEX, &message); + + switch (msg) + { + case WM_CREATE: + red_brush = CreateSolidBrush(RGB(255, 0, 0)); + break; + case WM_CLOSE: + DeleteObject(red_brush); + PostQuitMessage(0); + return 0; + case WM_CTLCOLORSCROLLBAR: + return (INT_PTR)red_brush; + } + + InterlockedIncrement(&defwndproc_counter); + ret = DefWindowProcA(hwnd, msg, wp, lp); + InterlockedDecrement(&defwndproc_counter); + return ret; +} + +static void test_scrollbar(void) +{ + WNDCLASSA cls = {0}; + BOOL transparent; + HWND hwnd, child; + COLORREF color; + HTHEME htheme; + HRESULT hr; + HDC hdc; + + /* Test that scrollbar arrow parts are transparent */ + hwnd = CreateWindowA(WC_STATICA, "", WS_POPUP, 0, 0, 1, 1, 0, 0, 0, NULL); + ok(!!hwnd, "CreateWindowA failed, error %#lx.\n", GetLastError()); + htheme = OpenThemeData(hwnd, L"ScrollBar"); + if (htheme) + { + transparent = FALSE; + hr = GetThemeBool(htheme, SBP_ARROWBTN, 0, TMT_TRANSPARENT, &transparent); + /* XP does use opaque scrollbar arrow parts and TMT_TRANSPARENT is FALSE */ + if (LOBYTE(LOWORD(GetVersion())) < 6) + { + ok(hr == E_PROP_ID_UNSUPPORTED, "Got unexpected hr %#lx.\n", hr); + + transparent = IsThemeBackgroundPartiallyTransparent(htheme, SBP_ARROWBTN, 0); + ok(!transparent, "Expected opaque.\n"); + } + /* > XP use opaque scrollbar arrow parts, but TMT_TRANSPARENT is TRUE */ + else + { + ok(hr == S_OK, "Got unexpected hr %#lx,\n", hr); + ok(transparent, "Expected transparent.\n"); + + transparent = IsThemeBackgroundPartiallyTransparent(htheme, SBP_ARROWBTN, 0); + ok(transparent, "Expected transparent.\n"); + } + + CloseThemeData(htheme); + } + else + { + skip("Theming is inactive.\n"); + } + DestroyWindow(hwnd); + + cls.hInstance = GetModuleHandleA(0); + cls.hCursor = LoadCursorA(0, (LPCSTR)IDC_ARROW); + cls.hbrBackground = GetStockObject(WHITE_BRUSH); + cls.lpfnWndProc = TestScrollBarParentProcA; + cls.lpszClassName = "TestScrollBarParentClass"; + RegisterClassA(&cls); + + cls.lpfnWndProc = DefWindowProcA; + cls.lpszClassName = "TestScrollBarChildClass"; + RegisterClassA(&cls); + + hwnd = CreateWindowA("TestScrollBarParentClass", "parent", WS_OVERLAPPEDWINDOW | WS_VISIBLE, + 100, 100, 300, 300, 0, 0, 0, NULL); + ok(!!hwnd, "Failed to create a parent window.\n"); + child = CreateWindowA("ScrollBar", "child", WS_CHILD | WS_VISIBLE | SBS_VERT, 0, 0, 20, 100, + hwnd, 0, 0, NULL); + ok(!!child, "Failed to create a child window.\n"); + flush_events(); + flush_sequences(sequences, NUM_MSG_SEQUENCES); + + /* Test that themed scrollbars don't paint parent background for arrows even if arrow parts are + * reported to be transparent. Note that there is no WM_PRINTCLIENT in wm_ctlcolorscrollbar_seq. + * If DrawThemeParentBackground() is called then WM_PRINTCLIENT must be present */ + RedrawWindow(child, NULL, NULL, RDW_INVALIDATE | RDW_ERASE | RDW_UPDATENOW | RDW_ERASENOW | RDW_FRAME); + ok_sequence(sequences, PARENT_SEQ_INDEX, wm_ctlcolorscrollbar_seq, "SB_CTL scrollbar paint", + IsThemeActive()); + + hdc = GetDC(child); + color = GetPixel(hdc, 10, 10); + ok(color != RGB(255, 0, 0), "Got unexpected color %#08lx.\n", color); + + /* The brush from WM_CTLCOLORSCROLLBAR is used to fill the lower and upper track if present */ + color = GetPixel(hdc, 10, 60); + todo_wine_if(IsThemeActive()) + ok(color == RGB(255, 0, 0) || broken(color == CLR_INVALID), /* Win7 on TestBots */ + "Got unexpected color %#08lx.\n", color); + ReleaseDC(child, hdc); + + DestroyWindow(child); + child = CreateWindowA("TestScrollBarChildClass", "child", WS_CHILD | WS_VISIBLE | WS_HSCROLL | WS_VSCROLL, + 0, 0, 100, 100, hwnd, 0, 0, NULL); + ok(!!child, "Failed to create a child window.\n"); + flush_events(); + flush_sequences(sequences, NUM_MSG_SEQUENCES); + + RedrawWindow(child, NULL, NULL, RDW_INVALIDATE | RDW_ERASE | RDW_UPDATENOW | RDW_ERASENOW | RDW_FRAME); + ok_sequence(sequences, PARENT_SEQ_INDEX, empty_seq, "SB_HORZ and SB_VERT scrollbar paint", FALSE); + + DestroyWindow(hwnd); + UnregisterClassA("TestScrollBarChildClass", GetModuleHandleA(0)); + UnregisterClassA("TestScrollBarParentClass", GetModuleHandleA(0)); +} + START_TEST(system) { ULONG_PTR ctx_cookie; @@ -2574,10 +2712,12 @@ START_TEST(system) test_DrawThemeParentBackground(); test_DrawThemeBackgroundEx(); test_GetThemeBackgroundRegion(); + test_scrollbar();
if (load_v6_module(&ctx_cookie, &ctx)) { test_EnableThemeDialogTexture(); + test_scrollbar();
unload_v6_module(ctx_cookie, ctx); }
From: Zhiyi Zhang zzhang@codeweavers.com
--- dlls/uxtheme/scrollbar.c | 32 ++++++++++++++++++++------------ dlls/uxtheme/tests/system.c | 1 - 2 files changed, 20 insertions(+), 13 deletions(-)
diff --git a/dlls/uxtheme/scrollbar.c b/dlls/uxtheme/scrollbar.c index 4ae1b2a8724..1f1c61d74e1 100644 --- a/dlls/uxtheme/scrollbar.c +++ b/dlls/uxtheme/scrollbar.c @@ -68,9 +68,13 @@ void WINAPI UXTHEME_ScrollBarDraw(HWND hwnd, HDC dc, INT bar, enum SCROLL_HITTES DrawThemeBackground(theme, dc, SBP_SIZEBOX, state, rect, NULL); } else { int uppertrackstate, lowertrackstate, thumbstate; + HBRUSH track_brush = NULL; RECT partrect; SIZE grippersize;
+ if (bar == SB_CTL) + track_brush = (HBRUSH)SendMessageW(GetParent(hwnd), WM_CTLCOLORSCROLLBAR, (WPARAM)dc, (LPARAM)hwnd); + if (disabled) { uppertrackstate = SCRBS_DISABLED; lowertrackstate = SCRBS_DISABLED; @@ -148,9 +152,10 @@ void WINAPI UXTHEME_ScrollBarDraw(HWND hwnd, HDC dc, INT bar, enum SCROLL_HITTES partrect.top = rect->top + arrowsize; partrect.bottom = rect->top + thumbpos;
- if (bar == SB_CTL && IsThemeBackgroundPartiallyTransparent(theme, SBP_UPPERTRACKVERT, uppertrackstate)) - DrawThemeParentBackground(hwnd, dc, &partrect); - DrawThemeBackground(theme, dc, SBP_UPPERTRACKVERT, uppertrackstate, &partrect, NULL); + if (bar == SB_CTL && track_brush) + FillRect(dc, &partrect, track_brush); + else + DrawThemeBackground(theme, dc, SBP_UPPERTRACKVERT, uppertrackstate, &partrect, NULL); }
if (thumbsize > 0) { @@ -178,9 +183,10 @@ void WINAPI UXTHEME_ScrollBarDraw(HWND hwnd, HDC dc, INT bar, enum SCROLL_HITTES partrect.top = rect->top + arrowsize; if (partrect.bottom > partrect.top) { - if (bar == SB_CTL && IsThemeBackgroundPartiallyTransparent(theme, SBP_LOWERTRACKVERT, lowertrackstate)) - DrawThemeParentBackground(hwnd, dc, &partrect); - DrawThemeBackground(theme, dc, SBP_LOWERTRACKVERT, lowertrackstate, &partrect, NULL); + if (bar == SB_CTL && track_brush) + FillRect(dc, &partrect, track_brush); + else + DrawThemeBackground(theme, dc, SBP_LOWERTRACKVERT, lowertrackstate, &partrect, NULL); } } else { int leftarrowstate, rightarrowstate; @@ -225,9 +231,10 @@ void WINAPI UXTHEME_ScrollBarDraw(HWND hwnd, HDC dc, INT bar, enum SCROLL_HITTES partrect.left = rect->left + arrowsize; partrect.right = rect->left + thumbpos;
- if (bar == SB_CTL && IsThemeBackgroundPartiallyTransparent(theme, SBP_UPPERTRACKHORZ, uppertrackstate)) - DrawThemeParentBackground(hwnd, dc, &partrect); - DrawThemeBackground(theme, dc, SBP_UPPERTRACKHORZ, uppertrackstate, &partrect, NULL); + if (bar == SB_CTL && track_brush) + FillRect(dc, &partrect, track_brush); + else + DrawThemeBackground(theme, dc, SBP_UPPERTRACKHORZ, uppertrackstate, &partrect, NULL); }
if (thumbsize > 0) { @@ -255,9 +262,10 @@ void WINAPI UXTHEME_ScrollBarDraw(HWND hwnd, HDC dc, INT bar, enum SCROLL_HITTES partrect.left = rect->left + arrowsize; if (partrect.right > partrect.left) { - if (bar == SB_CTL && IsThemeBackgroundPartiallyTransparent(theme, SBP_LOWERTRACKHORZ, lowertrackstate)) - DrawThemeParentBackground(hwnd, dc, &partrect); - DrawThemeBackground(theme, dc, SBP_LOWERTRACKHORZ, lowertrackstate, &partrect, NULL); + if (bar == SB_CTL && track_brush) + FillRect(dc, &partrect, track_brush); + else + DrawThemeBackground(theme, dc, SBP_LOWERTRACKHORZ, lowertrackstate, &partrect, NULL); } } } diff --git a/dlls/uxtheme/tests/system.c b/dlls/uxtheme/tests/system.c index f0f51a68009..71928ca4670 100644 --- a/dlls/uxtheme/tests/system.c +++ b/dlls/uxtheme/tests/system.c @@ -2668,7 +2668,6 @@ static void test_scrollbar(void)
/* The brush from WM_CTLCOLORSCROLLBAR is used to fill the lower and upper track if present */ color = GetPixel(hdc, 10, 60); - todo_wine_if(IsThemeActive()) ok(color == RGB(255, 0, 0) || broken(color == CLR_INVALID), /* Win7 on TestBots */ "Got unexpected color %#08lx.\n", color); ReleaseDC(child, hdc);
From: Zhiyi Zhang zzhang@codeweavers.com
This is confirmed by the tests in test_scrollbar() and manual tests on XP. Even though scrollbar arrows and thumb are in fact transparent, DrawThemeParentBackground() is not called to paint the parent background, leaving the transparent area untouched. On Windows, even if the scrollbar arrows are reported to be transparent, the bitmaps for arrow parts in the stock themes are in fact opaque.
Fix Ice Cream Calculator slow scrolling after 4cb229a because the WM_PRINTCLIENT handling in the application is slow.
Wine-Bug: https://bugs.winehq.org/show_bug.cgi?id=53337 --- dlls/uxtheme/scrollbar.c | 14 -------------- dlls/uxtheme/tests/system.c | 2 +- 2 files changed, 1 insertion(+), 15 deletions(-)
diff --git a/dlls/uxtheme/scrollbar.c b/dlls/uxtheme/scrollbar.c index 1f1c61d74e1..d5735c5279a 100644 --- a/dlls/uxtheme/scrollbar.c +++ b/dlls/uxtheme/scrollbar.c @@ -138,14 +138,10 @@ void WINAPI UXTHEME_ScrollBarDraw(HWND hwnd, HDC dc, INT bar, enum SCROLL_HITTES
partrect = *rect; partrect.bottom = partrect.top + arrowsize; - if (bar == SB_CTL && IsThemeBackgroundPartiallyTransparent(theme, SBP_ARROWBTN, uparrowstate)) - DrawThemeParentBackground(hwnd, dc, &partrect); DrawThemeBackground(theme, dc, SBP_ARROWBTN, uparrowstate, &partrect, NULL);
partrect.bottom = rect->bottom; partrect.top = partrect.bottom - arrowsize; - if (bar == SB_CTL && IsThemeBackgroundPartiallyTransparent(theme, SBP_ARROWBTN, downarrowstate)) - DrawThemeParentBackground(hwnd, dc, &partrect); DrawThemeBackground(theme, dc, SBP_ARROWBTN, downarrowstate, &partrect, NULL);
if (thumbpos > 0) { @@ -161,9 +157,6 @@ void WINAPI UXTHEME_ScrollBarDraw(HWND hwnd, HDC dc, INT bar, enum SCROLL_HITTES if (thumbsize > 0) { partrect.top = rect->top + thumbpos; partrect.bottom = partrect.top + thumbsize; - - if (bar == SB_CTL && IsThemeBackgroundPartiallyTransparent(theme, SBP_THUMBBTNVERT, thumbstate)) - DrawThemeParentBackground(hwnd, dc, &partrect); DrawThemeBackground(theme, dc, SBP_THUMBBTNVERT, thumbstate, &partrect, NULL);
if (SUCCEEDED(GetThemePartSize(theme, dc, SBP_GRIPPERVERT, thumbstate, NULL, TS_DRAW, &grippersize))) { @@ -217,14 +210,10 @@ void WINAPI UXTHEME_ScrollBarDraw(HWND hwnd, HDC dc, INT bar, enum SCROLL_HITTES
partrect = *rect; partrect.right = partrect.left + arrowsize; - if (bar == SB_CTL && IsThemeBackgroundPartiallyTransparent(theme, SBP_ARROWBTN, leftarrowstate)) - DrawThemeParentBackground(hwnd, dc, &partrect); DrawThemeBackground(theme, dc, SBP_ARROWBTN, leftarrowstate, &partrect, NULL);
partrect.right = rect->right; partrect.left = partrect.right - arrowsize; - if (bar == SB_CTL && IsThemeBackgroundPartiallyTransparent(theme, SBP_ARROWBTN, rightarrowstate)) - DrawThemeParentBackground(hwnd, dc, &partrect); DrawThemeBackground(theme, dc, SBP_ARROWBTN, rightarrowstate, &partrect, NULL);
if (thumbpos > 0) { @@ -240,9 +229,6 @@ void WINAPI UXTHEME_ScrollBarDraw(HWND hwnd, HDC dc, INT bar, enum SCROLL_HITTES if (thumbsize > 0) { partrect.left = rect->left + thumbpos; partrect.right = partrect.left + thumbsize; - - if (bar == SB_CTL && IsThemeBackgroundPartiallyTransparent(theme, SBP_THUMBBTNHORZ, thumbstate)) - DrawThemeParentBackground(hwnd, dc, &partrect); DrawThemeBackground(theme, dc, SBP_THUMBBTNHORZ, thumbstate, &partrect, NULL);
if (SUCCEEDED(GetThemePartSize(theme, dc, SBP_GRIPPERHORZ, thumbstate, NULL, TS_DRAW, &grippersize))) { diff --git a/dlls/uxtheme/tests/system.c b/dlls/uxtheme/tests/system.c index 71928ca4670..1f004e5c5dd 100644 --- a/dlls/uxtheme/tests/system.c +++ b/dlls/uxtheme/tests/system.c @@ -2660,7 +2660,7 @@ static void test_scrollbar(void) * If DrawThemeParentBackground() is called then WM_PRINTCLIENT must be present */ RedrawWindow(child, NULL, NULL, RDW_INVALIDATE | RDW_ERASE | RDW_UPDATENOW | RDW_ERASENOW | RDW_FRAME); ok_sequence(sequences, PARENT_SEQ_INDEX, wm_ctlcolorscrollbar_seq, "SB_CTL scrollbar paint", - IsThemeActive()); + FALSE);
hdc = GetDC(child); color = GetPixel(hdc, 10, 10);
From: Zhiyi Zhang zzhang@codeweavers.com
This is tested manually on XP, Win7 and Win10. --- dlls/comctl32/datetime.c | 2 -- 1 file changed, 2 deletions(-)
diff --git a/dlls/comctl32/datetime.c b/dlls/comctl32/datetime.c index f142ea8ede5..53c17798668 100644 --- a/dlls/comctl32/datetime.c +++ b/dlls/comctl32/datetime.c @@ -793,8 +793,6 @@ DATETIME_Refresh (DATETIME_INFO *infoPtr, HDC hdc) else state = ABS_DOWNNORMAL;
- if (IsThemeBackgroundPartiallyTransparent(theme, SBP_ARROWBTN, state)) - DrawThemeParentBackground(infoPtr->hwndSelf, hdc, &infoPtr->calbutton); DrawThemeBackground(theme, hdc, SBP_ARROWBTN, state, &infoPtr->calbutton, NULL); } else
Hi,
It looks like your patch introduced the new failures shown below. Please investigate and fix them before resubmitting your patch. If they are not new, fixing them anyway would help a lot. Otherwise please ask for the known failures list to be updated.
The full results can be found at: https://testbot.winehq.org/JobDetails.pl?Key=122363
Your paranoid android.
=== debian11 (32 bit report) ===
comctl32: misc.c:933: Test succeeded inside todo block: ScrollBar 0: paint background: marked "todo_wine" but succeeds
=== debian11 (32 bit Chinese:China report) ===
comctl32: misc.c:933: Test succeeded inside todo block: ScrollBar 0: paint background: marked "todo_wine" but succeeds
=== debian11 (32 bit WoW report) ===
comctl32: misc.c:933: Test succeeded inside todo block: ScrollBar 0: paint background: marked "todo_wine" but succeeds
=== debian11 (64 bit WoW report) ===
comctl32: misc.c:933: Test succeeded inside todo block: ScrollBar 0: paint background: marked "todo_wine" but succeeds