Signed-off-by: Rémi Bernon rbernon@codeweavers.com --- dlls/user32/driver.c | 130 +++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 130 insertions(+)
diff --git a/dlls/user32/driver.c b/dlls/user32/driver.c index 68c10bf4d9a..4deaf73a025 100644 --- a/dlls/user32/driver.c +++ b/dlls/user32/driver.c @@ -20,6 +20,8 @@
#include <stdarg.h> #include <stdio.h> +#include <stdlib.h> +#include <limits.h> #include <wchar.h>
#include "windef.h" @@ -188,6 +190,132 @@ void USER_unload_driver(void) * These are fallbacks for entry points that are not implemented in the real driver. */
+struct nulldrv_window_surface +{ + struct window_surface base; + BITMAPINFOHEADER info; + CRITICAL_SECTION cs; + RECT bounds; + char pixels[1]; +}; + +static const struct window_surface_funcs nulldrv_window_surface_funcs; + +static inline void reset_bounds( RECT *bounds ) +{ + bounds->left = bounds->top = INT_MAX; + bounds->right = bounds->bottom = INT_MIN; +} + +static struct nulldrv_window_surface *impl_from_window_surface( struct window_surface *base ) +{ + if (base->funcs != &nulldrv_window_surface_funcs) return NULL; + return CONTAINING_RECORD( base, struct nulldrv_window_surface, base ); +} + +static void CDECL nulldrv_window_surface_lock( struct window_surface *base ) +{ + struct nulldrv_window_surface *impl = impl_from_window_surface( base ); + EnterCriticalSection( &impl->cs ); +} + +static void CDECL nulldrv_window_surface_unlock( struct window_surface *base ) +{ + struct nulldrv_window_surface *impl = impl_from_window_surface( base ); + LeaveCriticalSection( &impl->cs ); +} + +static void *CDECL nulldrv_window_surface_get_bitmap_info( struct window_surface *base, BITMAPINFO *info ) +{ + struct nulldrv_window_surface *impl = impl_from_window_surface( base ); + info->bmiHeader = impl->info; + return impl->pixels; +} + +static RECT *CDECL nulldrv_window_surface_get_bounds( struct window_surface *base ) +{ + struct nulldrv_window_surface *impl = impl_from_window_surface( base ); + return &impl->bounds; +} + +static void CDECL nulldrv_window_surface_set_region( struct window_surface *base, HRGN region ) +{ + TRACE_(nulldrv)( "base %p, region %p\n", base, region ); +} + +static void CDECL nulldrv_window_surface_flush( struct window_surface *base ) +{ + struct nulldrv_window_surface *impl = impl_from_window_surface( base ); + reset_bounds( &impl->bounds ); +} + +static void CDECL nulldrv_window_surface_destroy( struct window_surface *base ) +{ + struct nulldrv_window_surface *impl = impl_from_window_surface( base ); + impl->cs.DebugInfo->Spare[0] = 0; + DeleteCriticalSection( &impl->cs ); + free( impl ); +} + +static const struct window_surface_funcs nulldrv_window_surface_funcs = +{ + nulldrv_window_surface_lock, + nulldrv_window_surface_unlock, + nulldrv_window_surface_get_bitmap_info, + nulldrv_window_surface_get_bounds, + nulldrv_window_surface_set_region, + nulldrv_window_surface_flush, + nulldrv_window_surface_destroy +}; + +static void nulldrv_update_window_surface( const RECT *visible_rect, struct window_surface **window_surface ) +{ + struct nulldrv_window_surface *impl = NULL; + struct window_surface *base; + SIZE_T size; + RECT surface_rect = *visible_rect; + + TRACE_(nulldrv)( "visible_rect %s, window_surface %p.\n", wine_dbgstr_rect( visible_rect ), window_surface ); + + OffsetRect( &surface_rect, -surface_rect.left, -surface_rect.top ); + size = 4 * surface_rect.right * surface_rect.bottom; + + /* check that old surface is a nulldrv_window_surface, or release it */ + if ((base = *window_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->base.rect )) return; + + /* create a new window surface */ + *window_surface = NULL; + if (impl) window_surface_release( &impl->base ); + if (!(impl = calloc(1, offsetof( struct nulldrv_window_surface, pixels[size] )))) return; + + impl->base.funcs = &nulldrv_window_surface_funcs; + impl->base.ref = 1; + impl->base.rect = surface_rect; + + impl->info.biSize = sizeof( impl->info ); + impl->info.biWidth = surface_rect.right; + impl->info.biHeight = surface_rect.bottom; + impl->info.biPlanes = 1; + impl->info.biBitCount = 32; + impl->info.biCompression = BI_RGB; + impl->info.biSizeImage = size; + impl->info.biXPelsPerMeter = 0; + impl->info.biYPelsPerMeter = 0; + impl->info.biClrUsed = 0; + impl->info.biClrImportant = 0; + + InitializeCriticalSection( &impl->cs ); + impl->cs.DebugInfo->Spare[0] = (DWORD_PTR)(__FILE__ ": surface"); + reset_bounds( &impl->bounds ); + + TRACE_(nulldrv)( "created window surface %p\n", &impl->base ); + + *window_surface = &impl->base; +} + static HKL CDECL nulldrv_ActivateKeyboardLayout( HKL layout, UINT flags ) { TRACE_(nulldrv)("layout %p, flags %x.\n", layout, flags); @@ -511,6 +639,8 @@ static void CDECL nulldrv_WindowPosChanging( HWND hwnd, HWND insert_after, UINT TRACE_(nulldrv)("hwnd %p, insert_after %p, swp_flags %x, window_rect %s, client_rect %s, visible_rect %s, surface %p.\n", hwnd, insert_after, swp_flags, wine_dbgstr_rect(window_rect), wine_dbgstr_rect(client_rect), wine_dbgstr_rect(visible_rect), surface); + + if (surface && *surface) nulldrv_update_window_surface( visible_rect, surface ); }
static void CDECL nulldrv_WindowPosChanged( HWND hwnd, HWND insert_after, UINT swp_flags,