From 4bb7e5af52a582568aec9196d151c24b83311ab1 Mon Sep 17 00:00:00 2001 From: Jacek Caban Date: Mon, 14 Mar 2022 11:45:01 +0100 Subject: [PATCH] win32u: Mmove dummy surface implementation from user32. Signed-off-by: Jacek Caban Signed-off-by: Huw Davies Signed-off-by: Alexandre Julliard --- dlls/user32/painting.c | 4 +- dlls/user32/win.c | 68 ---------------------- dlls/user32/win.h | 1 - dlls/user32/winpos.c | 7 ++- dlls/win32u/dce.c | 110 +++++++++++++++++++++++++++++++++++ dlls/win32u/win32u_private.h | 9 ++- dlls/win32u/window.c | 43 +------------- include/ntuser.h | 1 + 8 files changed, 126 insertions(+), 117 deletions(-) diff --git a/dlls/user32/painting.c b/dlls/user32/painting.c index 2f8ab9b81f8..6254a2d599c 100644 --- a/dlls/user32/painting.c +++ b/dlls/user32/painting.c @@ -169,9 +169,11 @@ static void update_visible_region( struct dce *dce ) */ static void release_dce( struct dce *dce ) { + struct window_surface *dummy_surface = (struct window_surface *)NtUserCallHwnd( 0, NtUserGetDummySurface ); + if (!dce->hwnd) return; /* already released */ - __wine_set_visible_region( dce->hdc, 0, &dummy_surface.rect, &dummy_surface.rect, &dummy_surface ); + __wine_set_visible_region( dce->hdc, 0, &dummy_surface->rect, &dummy_surface->rect, dummy_surface ); USER_Driver->pReleaseDC( dce->hwnd, dce->hdc ); if (dce->clip_rgn) DeleteObject( dce->clip_rgn ); diff --git a/dlls/user32/win.c b/dlls/user32/win.c index 58ff58634cf..e432d48624c 100644 --- a/dlls/user32/win.c +++ b/dlls/user32/win.c @@ -365,72 +365,6 @@ BOOL is_desktop_window( HWND hwnd ) } -/******************************************************************* - * Dummy window surface for windows that shouldn't get painted. - */ - -static void CDECL dummy_surface_lock( struct window_surface *window_surface ) -{ - /* nothing to do */ -} - -static void CDECL dummy_surface_unlock( struct window_surface *window_surface ) -{ - /* nothing to do */ -} - -static void *CDECL dummy_surface_get_bitmap_info( struct window_surface *window_surface, BITMAPINFO *info ) -{ - static DWORD dummy_data; - - info->bmiHeader.biSize = sizeof( info->bmiHeader ); - info->bmiHeader.biWidth = dummy_surface.rect.right; - info->bmiHeader.biHeight = dummy_surface.rect.bottom; - info->bmiHeader.biPlanes = 1; - info->bmiHeader.biBitCount = 32; - info->bmiHeader.biCompression = BI_RGB; - info->bmiHeader.biSizeImage = 0; - info->bmiHeader.biXPelsPerMeter = 0; - info->bmiHeader.biYPelsPerMeter = 0; - info->bmiHeader.biClrUsed = 0; - info->bmiHeader.biClrImportant = 0; - return &dummy_data; -} - -static RECT *CDECL dummy_surface_get_bounds( struct window_surface *window_surface ) -{ - static RECT dummy_bounds; - return &dummy_bounds; -} - -static void CDECL dummy_surface_set_region( struct window_surface *window_surface, HRGN region ) -{ - /* nothing to do */ -} - -static void CDECL dummy_surface_flush( struct window_surface *window_surface ) -{ - /* nothing to do */ -} - -static void CDECL dummy_surface_destroy( struct window_surface *window_surface ) -{ - /* nothing to do */ -} - -static const struct window_surface_funcs dummy_surface_funcs = -{ - dummy_surface_lock, - dummy_surface_unlock, - dummy_surface_get_bitmap_info, - dummy_surface_get_bounds, - dummy_surface_set_region, - dummy_surface_flush, - dummy_surface_destroy -}; - -struct window_surface dummy_surface = { &dummy_surface_funcs, { NULL, NULL }, 1, { 0, 0, 1, 1 } }; - /******************************************************************* * Off-screen window surface. */ @@ -569,8 +503,6 @@ void create_offscreen_window_surface( const RECT *visible_rect, struct window_su */ void register_window_surface( struct window_surface *old, struct window_surface *new ) { - if (old == &dummy_surface) old = NULL; - if (new == &dummy_surface) new = NULL; NtUserCallTwoParam( (UINT_PTR)old, (UINT_PTR)new, NtUserRegisterWindowSurface ); } diff --git a/dlls/user32/win.h b/dlls/user32/win.h index 3a1ec75169b..6bb69e77df0 100644 --- a/dlls/user32/win.h +++ b/dlls/user32/win.h @@ -36,7 +36,6 @@ struct tagDIALOGINFO; /* Window functions */ extern HWND get_hwnd_message_parent(void) DECLSPEC_HIDDEN; extern BOOL is_desktop_window( HWND hwnd ) DECLSPEC_HIDDEN; -extern struct window_surface dummy_surface DECLSPEC_HIDDEN; extern void register_window_surface( struct window_surface *old, struct window_surface *new ) DECLSPEC_HIDDEN; extern void flush_window_surfaces( BOOL idle ) DECLSPEC_HIDDEN; extern WND *WIN_GetPtr( HWND hwnd ) DECLSPEC_HIDDEN; diff --git a/dlls/user32/winpos.c b/dlls/user32/winpos.c index 3238d0c1b50..017337a1cb9 100644 --- a/dlls/user32/winpos.c +++ b/dlls/user32/winpos.c @@ -1976,10 +1976,11 @@ BOOL set_window_pos( HWND hwnd, HWND insert_after, UINT swp_flags, BOOL ret, needs_update = FALSE; RECT visible_rect, old_visible_rect, old_window_rect, old_client_rect, extra_rects[3]; struct window_surface *old_surface, *new_surface = NULL; + struct window_surface *dummy_surface = (struct window_surface *)NtUserCallHwnd( 0, NtUserGetDummySurface ); if (!parent || parent == GetDesktopWindow()) { - new_surface = &dummy_surface; /* provide a default surface for top-level windows */ + new_surface = dummy_surface; /* provide a default surface for top-level windows */ window_surface_add_ref( new_surface ); } visible_rect = *window_rect; @@ -2017,8 +2018,8 @@ BOOL set_window_pos( HWND hwnd, HWND insert_after, UINT swp_flags, old_client_rect = win->client_rect; old_surface = win->surface; if (old_surface != new_surface) swp_flags |= SWP_FRAMECHANGED; /* force refreshing non-client area */ - if (new_surface == &dummy_surface) swp_flags |= SWP_NOREDRAW; - else if (old_surface == &dummy_surface) + if (new_surface == dummy_surface) swp_flags |= SWP_NOREDRAW; + else if (old_surface == dummy_surface) { swp_flags |= SWP_NOCOPYBITS; valid_rects = NULL; diff --git a/dlls/win32u/dce.c b/dlls/win32u/dce.c index a811f7eae7f..6c43494cf0c 100644 --- a/dlls/win32u/dce.c +++ b/dlls/win32u/dce.c @@ -23,9 +23,119 @@ #pragma makedep unix #endif +#include #include "ntgdi_private.h" #include "ntuser_private.h" + +static struct list window_surfaces = LIST_INIT( window_surfaces ); +static pthread_mutex_t surfaces_lock = PTHREAD_MUTEX_INITIALIZER; + +/******************************************************************* + * Dummy window surface for windows that shouldn't get painted. + */ + +static void CDECL dummy_surface_lock( struct window_surface *window_surface ) +{ + /* nothing to do */ +} + +static void CDECL dummy_surface_unlock( struct window_surface *window_surface ) +{ + /* nothing to do */ +} + +static void *CDECL dummy_surface_get_bitmap_info( struct window_surface *window_surface, BITMAPINFO *info ) +{ + static DWORD dummy_data; + + info->bmiHeader.biSize = sizeof( info->bmiHeader ); + info->bmiHeader.biWidth = dummy_surface.rect.right; + info->bmiHeader.biHeight = dummy_surface.rect.bottom; + info->bmiHeader.biPlanes = 1; + info->bmiHeader.biBitCount = 32; + info->bmiHeader.biCompression = BI_RGB; + info->bmiHeader.biSizeImage = 0; + info->bmiHeader.biXPelsPerMeter = 0; + info->bmiHeader.biYPelsPerMeter = 0; + info->bmiHeader.biClrUsed = 0; + info->bmiHeader.biClrImportant = 0; + return &dummy_data; +} + +static RECT *CDECL dummy_surface_get_bounds( struct window_surface *window_surface ) +{ + static RECT dummy_bounds; + return &dummy_bounds; +} + +static void CDECL dummy_surface_set_region( struct window_surface *window_surface, HRGN region ) +{ + /* nothing to do */ +} + +static void CDECL dummy_surface_flush( struct window_surface *window_surface ) +{ + /* nothing to do */ +} + +static void CDECL dummy_surface_destroy( struct window_surface *window_surface ) +{ + /* nothing to do */ +} + +static const struct window_surface_funcs dummy_surface_funcs = +{ + dummy_surface_lock, + dummy_surface_unlock, + dummy_surface_get_bitmap_info, + dummy_surface_get_bounds, + dummy_surface_set_region, + dummy_surface_flush, + dummy_surface_destroy +}; + +struct window_surface dummy_surface = { &dummy_surface_funcs, { NULL, NULL }, 1, { 0, 0, 1, 1 } }; + +/******************************************************************* + * register_window_surface + * + * Register a window surface in the global list, possibly replacing another one. + */ +void register_window_surface( struct window_surface *old, struct window_surface *new ) +{ + if (old == &dummy_surface) old = NULL; + if (new == &dummy_surface) new = NULL; + if (old == new) return; + pthread_mutex_lock( &surfaces_lock ); + if (old) list_remove( &old->entry ); + if (new) list_add_tail( &window_surfaces, &new->entry ); + pthread_mutex_unlock( &surfaces_lock ); +} + +/******************************************************************* + * flush_window_surfaces + * + * Flush pending output from all window surfaces. + */ +void flush_window_surfaces( BOOL idle ) +{ + static DWORD last_idle; + DWORD now; + struct window_surface *surface; + + pthread_mutex_lock( &surfaces_lock ); + now = NtGetTickCount(); + if (idle) last_idle = now; + /* if not idle, we only flush if there's evidence that the app never goes idle */ + else if ((int)(now - last_idle) < 50) goto done; + + LIST_FOR_EACH_ENTRY( surface, &window_surfaces, struct window_surface, entry ) + surface->funcs->flush( surface ); +done: + pthread_mutex_unlock( &surfaces_lock ); +} + /********************************************************************** * NtUserWindowFromDC (win32u.@) */ diff --git a/dlls/win32u/win32u_private.h b/dlls/win32u/win32u_private.h index 14369ef5219..584e986b1a9 100644 --- a/dlls/win32u/win32u_private.h +++ b/dlls/win32u/win32u_private.h @@ -280,6 +280,12 @@ extern BOOL get_clip_cursor( RECT *rect ) DECLSPEC_HIDDEN; extern ULONG_PTR get_icon_param( HICON handle ) DECLSPEC_HIDDEN; extern ULONG_PTR set_icon_param( HICON handle, ULONG_PTR param ) DECLSPEC_HIDDEN; +/* dce.c */ +extern struct window_surface dummy_surface DECLSPEC_HIDDEN; +extern void flush_window_surfaces( BOOL idle ) DECLSPEC_HIDDEN; +extern void register_window_surface( struct window_surface *old, + struct window_surface *new ) DECLSPEC_HIDDEN; + /* hook.c */ extern LRESULT call_current_hook( HHOOK hhook, INT code, WPARAM wparam, LPARAM lparam ) DECLSPEC_HIDDEN; extern LRESULT call_hooks( INT id, INT code, WPARAM wparam, LPARAM lparam, BOOL unicode ) DECLSPEC_HIDDEN; @@ -327,13 +333,10 @@ extern BOOL get_window_placement( HWND hwnd, WINDOWPLACEMENT *placement ) DECLSP extern DWORD get_window_thread( HWND hwnd, DWORD *process ) DECLSPEC_HIDDEN; extern HWND is_current_thread_window( HWND hwnd ) DECLSPEC_HIDDEN; extern BOOL is_iconic( HWND hwnd ) DECLSPEC_HIDDEN; -extern void flush_window_surfaces( BOOL idle ) DECLSPEC_HIDDEN; extern DWORD get_window_long( HWND hwnd, INT offset ) DECLSPEC_HIDDEN; extern BOOL get_window_rect( HWND hwnd, RECT *rect, UINT dpi ) DECLSPEC_HIDDEN; extern HWND *list_window_children( HDESK desktop, HWND hwnd, UNICODE_STRING *class, DWORD tid ) DECLSPEC_HIDDEN; -extern void register_window_surface( struct window_surface *old, - struct window_surface *new ) DECLSPEC_HIDDEN; extern void update_window_state( HWND hwnd ) DECLSPEC_HIDDEN; /* to release pointers retrieved by win_get_ptr */ diff --git a/dlls/win32u/window.c b/dlls/win32u/window.c index 1e36e48aded..75d65afc9d0 100644 --- a/dlls/win32u/window.c +++ b/dlls/win32u/window.c @@ -23,7 +23,6 @@ #pragma makedep unix #endif -#include #include #include "ntstatus.h" @@ -40,9 +39,6 @@ WINE_DEFAULT_DEBUG_CHANNEL(win); static void *user_handles[NB_USER_HANDLES]; -static struct list window_surfaces = LIST_INIT( window_surfaces ); -static pthread_mutex_t surfaces_lock = PTHREAD_MUTEX_INITIALIZER; - /*********************************************************************** * alloc_user_handle */ @@ -206,43 +202,6 @@ HWND get_full_window_handle( HWND hwnd ) return hwnd; } -/******************************************************************* - * register_window_surface - * - * Register a window surface in the global list, possibly replacing another one. - */ -void register_window_surface( struct window_surface *old, struct window_surface *new ) -{ - if (old == new) return; - pthread_mutex_lock( &surfaces_lock ); - if (old) list_remove( &old->entry ); - if (new) list_add_tail( &window_surfaces, &new->entry ); - pthread_mutex_unlock( &surfaces_lock ); -} - -/******************************************************************* - * flush_window_surfaces - * - * Flush pending output from all window surfaces. - */ -void flush_window_surfaces( BOOL idle ) -{ - static DWORD last_idle; - DWORD now; - struct window_surface *surface; - - pthread_mutex_lock( &surfaces_lock ); - now = NtGetTickCount(); - if (idle) last_idle = now; - /* if not idle, we only flush if there's evidence that the app never goes idle */ - else if ((int)(now - last_idle) < 50) goto done; - - LIST_FOR_EACH_ENTRY( surface, &window_surfaces, struct window_surface, entry ) - surface->funcs->flush( surface ); -done: - pthread_mutex_unlock( &surfaces_lock ); -} - /******************************************************************* * is_desktop_window * @@ -1896,6 +1855,8 @@ ULONG_PTR WINAPI NtUserCallHwnd( HWND hwnd, DWORD code ) /* temporary exports */ case NtUserCreateDesktopWindow: return user_driver->pCreateDesktopWindow( hwnd ); + case NtUserGetDummySurface: + return (UINT_PTR)&dummy_surface; default: FIXME( "invalid code %u\n", code ); return 0; diff --git a/include/ntuser.h b/include/ntuser.h index fb8db926888..11fdcabb4d0 100644 --- a/include/ntuser.h +++ b/include/ntuser.h @@ -151,6 +151,7 @@ enum NtUserIsWindowVisible, /* temporary exports */ NtUserCreateDesktopWindow, + NtUserGetDummySurface, }; /* NtUserCallHwndParam codes, not compatible with Windows */