[PATCH 5/5] user32: Create a default window surface when driver doesn't.

Rémi Bernon rbernon at codeweavers.com
Mon May 10 02:55:13 CDT 2021


Signed-off-by: Rémi Bernon <rbernon at codeweavers.com>
---
 dlls/user32/driver.c          |   3 +-
 dlls/user32/user_private.h    |   3 +-
 dlls/user32/win.c             | 107 ++++++++++++++++++++++++++++++++++
 dlls/user32/winpos.c          |  13 ++++-
 dlls/wineandroid.drv/window.c |   9 +--
 dlls/winemac.drv/window.c     |   5 +-
 dlls/winex11.drv/window.c     |   7 ++-
 7 files changed, 134 insertions(+), 13 deletions(-)

diff --git a/dlls/user32/driver.c b/dlls/user32/driver.c
index 1c3b62eff2b..5f66ea6218e 100644
--- a/dlls/user32/driver.c
+++ b/dlls/user32/driver.c
@@ -375,10 +375,11 @@ static LRESULT CDECL nulldrv_WindowMessage( HWND hwnd, UINT msg, WPARAM wparam,
     return 0;
 }
 
-static void CDECL nulldrv_WindowPosChanging( HWND hwnd, HWND insert_after, UINT swp_flags,
+static BOOL CDECL nulldrv_WindowPosChanging( HWND hwnd, HWND insert_after, UINT swp_flags,
                                              const RECT *window_rect, const RECT *client_rect,
                                              RECT *visible_rect, struct window_surface **surface )
 {
+    return FALSE;
 }
 
 static void CDECL nulldrv_WindowPosChanged( HWND hwnd, HWND insert_after, UINT swp_flags,
diff --git a/dlls/user32/user_private.h b/dlls/user32/user_private.h
index db082462f1b..3afb2111957 100644
--- a/dlls/user32/user_private.h
+++ b/dlls/user32/user_private.h
@@ -105,7 +105,7 @@ typedef struct tagUSER_DRIVER {
     LRESULT (CDECL *pSysCommand)(HWND,WPARAM,LPARAM);
     BOOL    (CDECL *pUpdateLayeredWindow)(HWND,const UPDATELAYEREDWINDOWINFO *,const RECT *);
     LRESULT (CDECL *pWindowMessage)(HWND,UINT,WPARAM,LPARAM);
-    void   (CDECL *pWindowPosChanging)(HWND,HWND,UINT,const RECT *,const RECT *,RECT *,struct window_surface**);
+    BOOL   (CDECL *pWindowPosChanging)(HWND,HWND,UINT,const RECT *,const RECT *,RECT *,struct window_surface**);
     void   (CDECL *pWindowPosChanged)(HWND,HWND,UINT,const RECT *,const RECT *,const RECT *,const RECT *,struct window_surface*);
     /* system parameters */
     BOOL   (CDECL *pSystemParametersInfo)(UINT,UINT,void*,UINT);
@@ -242,6 +242,7 @@ extern BOOL rawinput_from_hardware_message(RAWINPUT *rawinput, const struct hard
 extern struct rawinput_thread_data *rawinput_thread_data(void);
 
 extern void keyboard_init(void) DECLSPEC_HIDDEN;
+extern void create_default_window_surface( const RECT *visible_rect, struct window_surface **surface ) DECLSPEC_HIDDEN;
 
 extern void CLIPBOARD_ReleaseOwner( HWND hwnd ) DECLSPEC_HIDDEN;
 extern BOOL FOCUS_MouseActivate( HWND hwnd ) DECLSPEC_HIDDEN;
diff --git a/dlls/user32/win.c b/dlls/user32/win.c
index 279d389f67c..6c2233c6e8b 100644
--- a/dlls/user32/win.c
+++ b/dlls/user32/win.c
@@ -22,6 +22,7 @@
 #include <stdarg.h>
 #include <stdlib.h>
 #include <string.h>
+#include <limits.h>
 
 #include "windef.h"
 #include "winbase.h"
@@ -583,6 +584,112 @@ static const struct window_surface_funcs dummy_surface_funcs =
 
 struct window_surface dummy_surface = { &dummy_surface_funcs, { NULL, NULL }, 1, { 0, 0, 1, 1 } };
 
+/*******************************************************************
+ * Off-screen default window surface.
+ */
+
+struct default_window_surface
+{
+    struct window_surface header;
+    char *bits;
+    BITMAPINFO info;
+};
+
+static const struct window_surface_funcs default_window_surface_funcs;
+
+static inline void reset_bounds( RECT *bounds )
+{
+    bounds->left = bounds->top = INT_MAX;
+    bounds->right = bounds->bottom = INT_MIN;
+}
+
+static struct default_window_surface *impl_from_window_surface( struct window_surface *base )
+{
+    if (base->funcs != &default_window_surface_funcs) return NULL;
+    return CONTAINING_RECORD( base, struct default_window_surface, header );
+}
+
+static void *CDECL default_window_surface_get_bitmap_info( struct window_surface *base, BITMAPINFO *info )
+{
+    struct default_window_surface *impl = impl_from_window_surface( base );
+    memcpy( info, &impl->info, offsetof( BITMAPINFO, bmiColors[0] ) );
+    return impl->bits;
+}
+
+static void CDECL default_window_surface_set_region( struct window_surface *base, HRGN region )
+{
+}
+
+static void CDECL default_window_surface_flush( struct window_surface *base )
+{
+    struct default_window_surface *impl = impl_from_window_surface( base );
+    window_surface_lock( base );
+    reset_bounds( &impl->header.bounds );
+    window_surface_unlock( base );
+}
+
+static void CDECL default_window_surface_destroy( struct window_surface *base )
+{
+    struct default_window_surface *impl = impl_from_window_surface( base );
+    impl->header.cs.DebugInfo->Spare[0] = 0;
+    DeleteCriticalSection( &impl->header.cs );
+    free( impl );
+}
+
+static const struct window_surface_funcs default_window_surface_funcs =
+{
+    NULL,
+    NULL,
+    default_window_surface_get_bitmap_info,
+    default_window_surface_set_region,
+    default_window_surface_flush,
+    default_window_surface_destroy
+};
+
+void create_default_window_surface( const RECT *visible_rect, struct window_surface **surface )
+{
+    struct default_window_surface *impl = NULL;
+    struct window_surface *base;
+    SIZE_T size;
+    RECT surface_rect = *visible_rect;
+
+    TRACE( "visible_rect %s, surface %p.\n", wine_dbgstr_rect( visible_rect ), surface );
+
+    OffsetRect( &surface_rect, -surface_rect.left, -surface_rect.top );
+    size = surface_rect.right * surface_rect.bottom * 4;
+
+    /* check that old surface is an default_window_surface, or release it */
+    if ((base = *surface) && !(impl = impl_from_window_surface( base ))) window_surface_release( base );
+
+    /* if the rect didn't change, keep the same surface */
+    if (impl && EqualRect( &surface_rect, &impl->header.rect )) return;
+
+    /* create a new window surface */
+    *surface = NULL;
+    if (impl) window_surface_release( &impl->header );
+    if (!(impl = calloc(1, offsetof( struct default_window_surface, info.bmiColors[0] ) + size))) return;
+
+    impl->header.funcs = &default_window_surface_funcs;
+    impl->header.ref = 1;
+    impl->header.rect = surface_rect;
+
+    InitializeCriticalSection( &impl->header.cs );
+    impl->header.cs.DebugInfo->Spare[0] = (DWORD_PTR)(__FILE__ ": surface");
+    reset_bounds( &impl->header.bounds );
+
+    impl->bits = (char *)&impl->info.bmiColors[0];
+    impl->info.bmiHeader.biSize        = sizeof( impl->info );
+    impl->info.bmiHeader.biWidth       = surface_rect.right;
+    impl->info.bmiHeader.biHeight      = surface_rect.bottom;
+    impl->info.bmiHeader.biPlanes      = 1;
+    impl->info.bmiHeader.biBitCount    = 32;
+    impl->info.bmiHeader.biCompression = BI_RGB;
+    impl->info.bmiHeader.biSizeImage   = size;
+
+    TRACE( "created window surface %p\n", &impl->header );
+
+    *surface = &impl->header;
+}
 
 /*******************************************************************
  *           register_window_surface
diff --git a/dlls/user32/winpos.c b/dlls/user32/winpos.c
index c6f806f7beb..f3f7bffbf97 100644
--- a/dlls/user32/winpos.c
+++ b/dlls/user32/winpos.c
@@ -2103,8 +2103,8 @@ BOOL set_window_pos( HWND hwnd, HWND insert_after, UINT swp_flags,
         window_surface_add_ref( new_surface );
     }
     visible_rect = *window_rect;
-    USER_Driver->pWindowPosChanging( hwnd, insert_after, swp_flags,
-                                     window_rect, client_rect, &visible_rect, &new_surface );
+    ret = USER_Driver->pWindowPosChanging( hwnd, insert_after, swp_flags,
+                                           window_rect, client_rect, &visible_rect, &new_surface );
 
     WIN_GetRectangles( hwnd, COORDS_SCREEN, &old_window_rect, NULL );
     if (IsRectEmpty( &valid_rects[0] )) valid_rects = NULL;
@@ -2114,6 +2114,15 @@ BOOL set_window_pos( HWND hwnd, HWND insert_after, UINT swp_flags,
         if (new_surface) window_surface_release( new_surface );
         return FALSE;
     }
+
+    /* create or update window surface if driver didn't */
+    if (!ret && new_surface && (!(GetWindowLongW( hwnd, GWL_EXSTYLE ) & WS_EX_LAYERED) || GetLayeredWindowAttributes( hwnd, NULL, NULL, NULL )))
+    {
+        window_surface_release(new_surface);
+        if ((new_surface = win->surface)) window_surface_add_ref( new_surface );
+        create_default_window_surface( &visible_rect, &new_surface );
+    }
+
     old_visible_rect = win->visible_rect;
     old_client_rect = win->client_rect;
     old_surface = win->surface;
diff --git a/dlls/wineandroid.drv/window.c b/dlls/wineandroid.drv/window.c
index f7373740c92..4c3d2553b08 100644
--- a/dlls/wineandroid.drv/window.c
+++ b/dlls/wineandroid.drv/window.c
@@ -1258,9 +1258,9 @@ static inline BOOL get_surface_rect( const RECT *visible_rect, RECT *surface_rec
 /***********************************************************************
  *           ANDROID_WindowPosChanging
  */
-void CDECL ANDROID_WindowPosChanging( HWND hwnd, HWND insert_after, UINT swp_flags,
-                                     const RECT *window_rect, const RECT *client_rect, RECT *visible_rect,
-                                     struct window_surface **surface )
+BOOL CDECL ANDROID_WindowPosChanging( HWND hwnd, HWND insert_after, UINT swp_flags,
+                                      const RECT *window_rect, const RECT *client_rect, RECT *visible_rect,
+                                      struct window_surface **surface )
 {
     struct android_win_data *data = get_win_data( hwnd );
     RECT surface_rect;
@@ -1273,7 +1273,7 @@ void CDECL ANDROID_WindowPosChanging( HWND hwnd, HWND insert_after, UINT swp_fla
            hwnd, wine_dbgstr_rect(window_rect), wine_dbgstr_rect(client_rect),
            GetWindowLongW( hwnd, GWL_STYLE ), swp_flags );
 
-    if (!data && !(data = create_win_data( hwnd, window_rect, client_rect ))) return;
+    if (!data && !(data = create_win_data( hwnd, window_rect, client_rect ))) return TRUE;
 
     *visible_rect = *window_rect;
 
@@ -1306,6 +1306,7 @@ void CDECL ANDROID_WindowPosChanging( HWND hwnd, HWND insert_after, UINT swp_fla
 
 done:
     release_win_data( data );
+    return TRUE;
 }
 
 
diff --git a/dlls/winemac.drv/window.c b/dlls/winemac.drv/window.c
index f23ac161244..7dfae0ddb23 100644
--- a/dlls/winemac.drv/window.c
+++ b/dlls/winemac.drv/window.c
@@ -2051,7 +2051,7 @@ static inline RECT get_surface_rect(const RECT *visible_rect)
 /***********************************************************************
  *              WindowPosChanging   (MACDRV.@)
  */
-void CDECL macdrv_WindowPosChanging(HWND hwnd, HWND insert_after, UINT swp_flags,
+BOOL CDECL macdrv_WindowPosChanging(HWND hwnd, HWND insert_after, UINT swp_flags,
                                     const RECT *window_rect, const RECT *client_rect,
                                     RECT *visible_rect, struct window_surface **surface)
 {
@@ -2063,7 +2063,7 @@ void CDECL macdrv_WindowPosChanging(HWND hwnd, HWND insert_after, UINT swp_flags
           swp_flags, wine_dbgstr_rect(window_rect), wine_dbgstr_rect(client_rect),
           wine_dbgstr_rect(visible_rect), surface);
 
-    if (!data && !(data = macdrv_create_win_data(hwnd, window_rect, client_rect))) return;
+    if (!data && !(data = macdrv_create_win_data(hwnd, window_rect, client_rect))) return TRUE;
 
     *visible_rect = *window_rect;
     macdrv_window_to_mac_rect(data, style, visible_rect, window_rect, client_rect);
@@ -2096,6 +2096,7 @@ void CDECL macdrv_WindowPosChanging(HWND hwnd, HWND insert_after, UINT swp_flags
 
 done:
     release_win_data(data);
+    return TRUE;
 }
 
 
diff --git a/dlls/winex11.drv/window.c b/dlls/winex11.drv/window.c
index 51078020c2f..31a84bd8567 100644
--- a/dlls/winex11.drv/window.c
+++ b/dlls/winex11.drv/window.c
@@ -2318,7 +2318,7 @@ static inline BOOL get_surface_rect( const RECT *visible_rect, RECT *surface_rec
 /***********************************************************************
  *		WindowPosChanging   (X11DRV.@)
  */
-void CDECL X11DRV_WindowPosChanging( HWND hwnd, HWND insert_after, UINT swp_flags,
+BOOL CDECL X11DRV_WindowPosChanging( HWND hwnd, HWND insert_after, UINT swp_flags,
                                      const RECT *window_rect, const RECT *client_rect, RECT *visible_rect,
                                      struct window_surface **surface )
 {
@@ -2328,7 +2328,7 @@ void CDECL X11DRV_WindowPosChanging( HWND hwnd, HWND insert_after, UINT swp_flag
     COLORREF key;
     BOOL layered = GetWindowLongW( hwnd, GWL_EXSTYLE ) & WS_EX_LAYERED;
 
-    if (!data && !(data = X11DRV_create_win_data( hwnd, window_rect, client_rect ))) return;
+    if (!data && !(data = X11DRV_create_win_data( hwnd, window_rect, client_rect ))) return TRUE;
 
     /* check if we need to switch the window to managed */
     if (!data->managed && data->whole_window && is_window_managed( hwnd, swp_flags, window_rect ))
@@ -2336,7 +2336,7 @@ void CDECL X11DRV_WindowPosChanging( HWND hwnd, HWND insert_after, UINT swp_flag
         TRACE( "making win %p/%lx managed\n", hwnd, data->whole_window );
         release_win_data( data );
         unmap_window( hwnd );
-        if (!(data = get_win_data( hwnd ))) return;
+        if (!(data = get_win_data( hwnd ))) return TRUE;
         data->managed = TRUE;
     }
 
@@ -2377,6 +2377,7 @@ void CDECL X11DRV_WindowPosChanging( HWND hwnd, HWND insert_after, UINT swp_flag
 
 done:
     release_win_data( data );
+    return TRUE;
 }
 
 
-- 
2.31.0




More information about the wine-devel mailing list