From: Fabian Maurer Subject: [PATCH v2 1/2] user32: SetSysColors updates brushes from GetSysColorBrush and add test Message-Id: <20170114210516.15759-1-dark.shadow4@web.de> Date: Sat, 14 Jan 2017 22:05:15 +0100 v2: Rewrote patch to make it cleaner Signed-off-by: Fabian Maurer --- dlls/gdi32/brush.c | 7 ++++++- dlls/gdi32/gdi32.spec | 1 + dlls/gdi32/gdi_private.h | 1 + dlls/gdi32/gdiobj.c | 30 ++++++++++++++++++++++++++++++ dlls/user32/sysparams.c | 16 ++++++++++------ dlls/user32/tests/sysparams.c | 16 ++++++++++++++++ include/wine/gdi_driver.h | 1 + 7 files changed, 65 insertions(+), 7 deletions(-) diff --git a/dlls/gdi32/brush.c b/dlls/gdi32/brush.c index 3c112439fe..8bf2117bef 100644 --- a/dlls/gdi32/brush.c +++ b/dlls/gdi32/brush.c @@ -470,7 +470,6 @@ static BOOL BRUSH_DeleteObject( HGDIOBJ handle ) return HeapFree( GetProcessHeap(), 0, brush ); } - /*********************************************************************** * BRUSH_GetObject */ @@ -488,3 +487,9 @@ static INT BRUSH_GetObject( HGDIOBJ handle, INT count, LPVOID buffer ) GDI_ReleaseObj( handle ); return count; } + +LOGBRUSH* BRUSH_internal_GetObject( HGDIOBJ handle ) +{ + BRUSHOBJ *brush = GDI_GetObjPtr( handle, OBJ_BRUSH ); + return &brush->logbrush; +} diff --git a/dlls/gdi32/gdi32.spec b/dlls/gdi32/gdi32.spec index 7792731b9e..8b9fd5a768 100644 --- a/dlls/gdi32/gdi32.spec +++ b/dlls/gdi32/gdi32.spec @@ -518,6 +518,7 @@ # GDI objects @ cdecl __wine_make_gdi_object_system(long long) @ cdecl __wine_set_visible_region(long long ptr ptr ptr) +@ cdecl __wine_set_gdi_object_color(ptr long long) # Graphics drivers @ cdecl __wine_set_display_driver(long) diff --git a/dlls/gdi32/gdi_private.h b/dlls/gdi32/gdi_private.h index e4633d1c33..f0835723ee 100644 --- a/dlls/gdi32/gdi_private.h +++ b/dlls/gdi32/gdi_private.h @@ -205,6 +205,7 @@ extern void get_mono_dc_colors( DC *dc, BITMAPINFO *info, int count ) DECLSPEC_H extern BOOL store_brush_pattern( LOGBRUSH *brush, struct brush_pattern *pattern ) DECLSPEC_HIDDEN; extern void free_brush_pattern( struct brush_pattern *pattern ) DECLSPEC_HIDDEN; extern BOOL get_brush_bitmap_info( HBRUSH handle, BITMAPINFO *info, void **bits, UINT *usage ) DECLSPEC_HIDDEN; +extern LOGBRUSH* BRUSH_internal_GetObject( HGDIOBJ handle ) DECLSPEC_HIDDEN; /* clipping.c */ extern BOOL clip_device_rect( DC *dc, RECT *dst, const RECT *src ) DECLSPEC_HIDDEN; diff --git a/dlls/gdi32/gdiobj.c b/dlls/gdi32/gdiobj.c index 46b2241945..6928557915 100644 --- a/dlls/gdi32/gdiobj.c +++ b/dlls/gdi32/gdiobj.c @@ -880,6 +880,36 @@ void GDI_ReleaseObj( HGDIOBJ handle ) LeaveCriticalSection( &gdi_section ); } +/* Export for user32, we need to be able to manipulate GDI objects where the official API doesn't allow us */ + +void CDECL __wine_set_gdi_object_color( HGDIOBJ handle, WORD type, COLORREF color ) +{ + struct gdi_handle_entry *entry; + + TRACE("%p, %u, %u\n", handle, type, color); + + if(!handle) + return; + + EnterCriticalSection( &gdi_section ); + + entry = handle_entry( handle ); + if(!entry || !entry->system) + { + WARN("Gdi handle invalid\n"); + LeaveCriticalSection( &gdi_section ); + return; + } + + if(type == OBJ_BRUSH) + { + LOGBRUSH *brush = BRUSH_internal_GetObject( handle ); + brush->lbColor = color; + GDI_ReleaseObj( handle ); + } + + LeaveCriticalSection( &gdi_section ); +} /*********************************************************************** * GDI_CheckNotLock diff --git a/dlls/user32/sysparams.c b/dlls/user32/sysparams.c index 63c4ffe070..ef464bff55 100644 --- a/dlls/user32/sysparams.c +++ b/dlls/user32/sysparams.c @@ -890,18 +890,12 @@ done: static BOOL set_rgb_entry( union sysparam_all_entry *entry, UINT int_param, void *ptr_param, UINT flags ) { WCHAR buf[32]; - HBRUSH brush; HPEN pen; wsprintfW( buf, CSrgb, GetRValue(int_param), GetGValue(int_param), GetBValue(int_param) ); if (!save_entry_string( &entry->hdr, buf, flags )) return FALSE; entry->rgb.val = int_param; entry->hdr.loaded = TRUE; - if ((brush = InterlockedExchangePointer( (void **)&entry->rgb.brush, 0 ))) - { - __wine_make_gdi_object_system( brush, FALSE ); - DeleteObject( brush ); - } if ((pen = InterlockedExchangePointer( (void **)&entry->rgb.pen, 0 ))) { __wine_make_gdi_object_system( pen, FALSE ); @@ -2647,6 +2641,13 @@ COLORREF WINAPI DECLSPEC_HOTPATCH GetSysColor( INT nIndex ) return ret; } +static void set_syscolors_gdi( INT index, COLORREF color ) +{ + HBRUSH brush = system_colors[index].brush; + + if(brush) + __wine_set_gdi_object_color( brush, OBJ_BRUSH, color); +} /************************************************************************* * SetSysColors (USER32.@) @@ -2659,7 +2660,10 @@ BOOL WINAPI SetSysColors( INT count, const INT *colors, const COLORREF *values ) for (i = 0; i < count; i++) if (colors[i] >= 0 && colors[i] <= NUM_SYS_COLORS) + { set_entry( &system_colors[colors[i]], values[i], 0, 0 ); + set_syscolors_gdi( colors[i], values[i] ); + } /* Send WM_SYSCOLORCHANGE message to all windows */ diff --git a/dlls/user32/tests/sysparams.c b/dlls/user32/tests/sysparams.c index 075a0c71f6..5d1895982c 100644 --- a/dlls/user32/tests/sysparams.c +++ b/dlls/user32/tests/sysparams.c @@ -2917,6 +2917,21 @@ static void test_GetSysColorBrush(void) win_skip("COLOR_MENUBAR unsupported\n"); } +static void test_SetSysColors(void) +{ + INT element = COLOR_WINDOW; + DWORD color_backup = GetSysColor(COLOR_WINDOW); /* Backup system colors */ + COLORREF color = RGB(0, 0, 255); + LOGBRUSH brush_info; + + HBRUSH brush = GetSysColorBrush(COLOR_WINDOW); + SetSysColors(1, &element, &color); + GetObjectW(brush, sizeof(LOGBRUSH), &brush_info); + ok(color == brush_info.lbColor, "Brush didn't update after SetSysColors\n"); + + SetSysColors(1, &element, &color_backup); /* Restore system colors */ +} + START_TEST(sysparams) { int argc; @@ -2948,6 +2963,7 @@ START_TEST(sysparams) trace("testing EnumDisplaySettings vs GetDeviceCaps\n"); test_EnumDisplaySettings( ); test_GetSysColorBrush( ); + test_SetSysColors( ); change_counter = 0; change_last_param = 0; diff --git a/include/wine/gdi_driver.h b/include/wine/gdi_driver.h index 6f67653b51..c3005c6ef3 100644 --- a/include/wine/gdi_driver.h +++ b/include/wine/gdi_driver.h @@ -276,6 +276,7 @@ WINGDIAPI WORD WINAPI SetHookFlags(HDC,WORD); extern void CDECL __wine_make_gdi_object_system( HGDIOBJ handle, BOOL set ); extern void CDECL __wine_set_visible_region( HDC hdc, HRGN hrgn, const RECT *vis_rect, const RECT *device_rect, struct window_surface *surface ); +extern void CDECL __wine_set_gdi_object_color( HGDIOBJ handle, WORD type, COLORREF color); extern void CDECL __wine_set_display_driver( HMODULE module ); extern struct opengl_funcs * CDECL __wine_get_wgl_driver( HDC hdc, UINT version ); -- 2.11.0