Commit 454712a9 authored by Rémi Bernon's avatar Rémi Bernon Committed by Alexandre Julliard

user32: Add a default WindowPosChanging implementation.

Which creates an off-screen window surface for top-level non-layered or SLWA-layered windows. Signed-off-by: 's avatarRémi Bernon <rbernon@codeweavers.com> Signed-off-by: 's avatarAlexandre Julliard <julliard@winehq.org>
parent d430efb6
...@@ -376,10 +376,11 @@ static LRESULT CDECL nulldrv_WindowMessage( HWND hwnd, UINT msg, WPARAM wparam, ...@@ -376,10 +376,11 @@ static LRESULT CDECL nulldrv_WindowMessage( HWND hwnd, UINT msg, WPARAM wparam,
return 0; 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, const RECT *window_rect, const RECT *client_rect,
RECT *visible_rect, struct window_surface **surface ) RECT *visible_rect, struct window_surface **surface )
{ {
return FALSE;
} }
static void CDECL nulldrv_WindowPosChanged( HWND hwnd, HWND insert_after, UINT swp_flags, static void CDECL nulldrv_WindowPosChanged( HWND hwnd, HWND insert_after, UINT swp_flags,
......
...@@ -105,7 +105,7 @@ typedef struct tagUSER_DRIVER { ...@@ -105,7 +105,7 @@ typedef struct tagUSER_DRIVER {
LRESULT (CDECL *pSysCommand)(HWND,WPARAM,LPARAM); LRESULT (CDECL *pSysCommand)(HWND,WPARAM,LPARAM);
BOOL (CDECL *pUpdateLayeredWindow)(HWND,const UPDATELAYEREDWINDOWINFO *,const RECT *); BOOL (CDECL *pUpdateLayeredWindow)(HWND,const UPDATELAYEREDWINDOWINFO *,const RECT *);
LRESULT (CDECL *pWindowMessage)(HWND,UINT,WPARAM,LPARAM); 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*); void (CDECL *pWindowPosChanged)(HWND,HWND,UINT,const RECT *,const RECT *,const RECT *,const RECT *,struct window_surface*);
/* system parameters */ /* system parameters */
BOOL (CDECL *pSystemParametersInfo)(UINT,UINT,void*,UINT); BOOL (CDECL *pSystemParametersInfo)(UINT,UINT,void*,UINT);
...@@ -242,6 +242,7 @@ extern BOOL rawinput_from_hardware_message(RAWINPUT *rawinput, const struct hard ...@@ -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 struct rawinput_thread_data *rawinput_thread_data(void);
extern void keyboard_init(void) DECLSPEC_HIDDEN; extern void keyboard_init(void) DECLSPEC_HIDDEN;
extern void create_offscreen_window_surface( const RECT *visible_rect, struct window_surface **surface ) DECLSPEC_HIDDEN;
extern void CLIPBOARD_ReleaseOwner( HWND hwnd ) DECLSPEC_HIDDEN; extern void CLIPBOARD_ReleaseOwner( HWND hwnd ) DECLSPEC_HIDDEN;
extern BOOL FOCUS_MouseActivate( HWND hwnd ) DECLSPEC_HIDDEN; extern BOOL FOCUS_MouseActivate( HWND hwnd ) DECLSPEC_HIDDEN;
......
...@@ -22,6 +22,7 @@ ...@@ -22,6 +22,7 @@
#include <stdarg.h> #include <stdarg.h>
#include <stdlib.h> #include <stdlib.h>
#include <string.h> #include <string.h>
#include <limits.h>
#include "windef.h" #include "windef.h"
#include "winbase.h" #include "winbase.h"
...@@ -590,6 +591,136 @@ static const struct window_surface_funcs dummy_surface_funcs = ...@@ -590,6 +591,136 @@ static const struct window_surface_funcs dummy_surface_funcs =
struct window_surface dummy_surface = { &dummy_surface_funcs, { NULL, NULL }, 1, { 0, 0, 1, 1 } }; struct window_surface dummy_surface = { &dummy_surface_funcs, { NULL, NULL }, 1, { 0, 0, 1, 1 } };
/*******************************************************************
* Off-screen window surface.
*/
struct offscreen_window_surface
{
struct window_surface header;
CRITICAL_SECTION cs;
RECT bounds;
char *bits;
BITMAPINFO info;
};
static const struct window_surface_funcs offscreen_window_surface_funcs;
static inline void reset_bounds( RECT *bounds )
{
bounds->left = bounds->top = INT_MAX;
bounds->right = bounds->bottom = INT_MIN;
}
static struct offscreen_window_surface *impl_from_window_surface( struct window_surface *base )
{
if (!base || base->funcs != &offscreen_window_surface_funcs) return NULL;
return CONTAINING_RECORD( base, struct offscreen_window_surface, header );
}
static void CDECL offscreen_window_surface_lock( struct window_surface *base )
{
struct offscreen_window_surface *impl = impl_from_window_surface( base );
EnterCriticalSection( &impl->cs );
}
static void CDECL offscreen_window_surface_unlock( struct window_surface *base )
{
struct offscreen_window_surface *impl = impl_from_window_surface( base );
LeaveCriticalSection( &impl->cs );
}
static RECT *CDECL offscreen_window_surface_get_bounds( struct window_surface *base )
{
struct offscreen_window_surface *impl = impl_from_window_surface( base );
return &impl->bounds;
}
static void *CDECL offscreen_window_surface_get_bitmap_info( struct window_surface *base, BITMAPINFO *info )
{
struct offscreen_window_surface *impl = impl_from_window_surface( base );
memcpy( info, &impl->info, offsetof( BITMAPINFO, bmiColors[0] ) );
return impl->bits;
}
static void CDECL offscreen_window_surface_set_region( struct window_surface *base, HRGN region )
{
}
static void CDECL offscreen_window_surface_flush( struct window_surface *base )
{
struct offscreen_window_surface *impl = impl_from_window_surface( base );
base->funcs->lock( base );
reset_bounds( &impl->bounds );
base->funcs->unlock( base );
}
static void CDECL offscreen_window_surface_destroy( struct window_surface *base )
{
struct offscreen_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 offscreen_window_surface_funcs =
{
offscreen_window_surface_lock,
offscreen_window_surface_unlock,
offscreen_window_surface_get_bitmap_info,
offscreen_window_surface_get_bounds,
offscreen_window_surface_set_region,
offscreen_window_surface_flush,
offscreen_window_surface_destroy
};
void create_offscreen_window_surface( const RECT *visible_rect, struct window_surface **surface )
{
struct offscreen_window_surface *impl;
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 );
surface_rect.right = (surface_rect.right + 0x1f) & ~0x1f;
surface_rect.bottom = (surface_rect.bottom + 0x1f) & ~0x1f;
/* check that old surface is an offscreen_window_surface, or release it */
if ((impl = impl_from_window_surface( *surface )))
{
/* if the rect didn't change, keep the same surface */
if (EqualRect( &surface_rect, &impl->header.rect )) return;
window_surface_release( &impl->header );
}
else if (*surface) window_surface_release( *surface );
/* create a new window surface */
*surface = NULL;
size = surface_rect.right * surface_rect.bottom * 4;
if (!(impl = calloc(1, offsetof( struct offscreen_window_surface, info.bmiColors[0] ) + size))) return;
impl->header.funcs = &offscreen_window_surface_funcs;
impl->header.ref = 1;
impl->header.rect = surface_rect;
InitializeCriticalSection( &impl->cs );
impl->cs.DebugInfo->Spare[0] = (DWORD_PTR)(__FILE__ ": surface");
reset_bounds( &impl->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 * register_window_surface
......
...@@ -2115,8 +2115,16 @@ BOOL set_window_pos( HWND hwnd, HWND insert_after, UINT swp_flags, ...@@ -2115,8 +2115,16 @@ BOOL set_window_pos( HWND hwnd, HWND insert_after, UINT swp_flags,
window_surface_add_ref( new_surface ); window_surface_add_ref( new_surface );
} }
visible_rect = *window_rect; visible_rect = *window_rect;
USER_Driver->pWindowPosChanging( hwnd, insert_after, swp_flags, if (!(ret = USER_Driver->pWindowPosChanging( hwnd, insert_after, swp_flags,
window_rect, client_rect, &visible_rect, &new_surface ); window_rect, client_rect, &visible_rect, &new_surface )))
{
if (IsRectEmpty( window_rect )) visible_rect = *window_rect;
else
{
visible_rect = get_virtual_screen_rect();
IntersectRect( &visible_rect, &visible_rect, window_rect );
}
}
WIN_GetRectangles( hwnd, COORDS_SCREEN, &old_window_rect, NULL ); WIN_GetRectangles( hwnd, COORDS_SCREEN, &old_window_rect, NULL );
if (IsRectEmpty( &valid_rects[0] )) valid_rects = NULL; if (IsRectEmpty( &valid_rects[0] )) valid_rects = NULL;
...@@ -2126,6 +2134,17 @@ BOOL set_window_pos( HWND hwnd, HWND insert_after, UINT swp_flags, ...@@ -2126,6 +2134,17 @@ BOOL set_window_pos( HWND hwnd, HWND insert_after, UINT swp_flags,
if (new_surface) window_surface_release( new_surface ); if (new_surface) window_surface_release( new_surface );
return FALSE; return FALSE;
} }
/* create or update window surface for top-level windows if the driver doesn't implement WindowPosChanging */
if (!ret && new_surface && !IsRectEmpty( &visible_rect ) &&
(!(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_offscreen_window_surface( &visible_rect, &new_surface );
}
old_visible_rect = win->visible_rect; old_visible_rect = win->visible_rect;
old_client_rect = win->client_rect; old_client_rect = win->client_rect;
old_surface = win->surface; old_surface = win->surface;
......
...@@ -1291,9 +1291,9 @@ static inline BOOL get_surface_rect( const RECT *visible_rect, RECT *surface_rec ...@@ -1291,9 +1291,9 @@ static inline BOOL get_surface_rect( const RECT *visible_rect, RECT *surface_rec
/*********************************************************************** /***********************************************************************
* ANDROID_WindowPosChanging * ANDROID_WindowPosChanging
*/ */
void CDECL ANDROID_WindowPosChanging( HWND hwnd, HWND insert_after, UINT swp_flags, BOOL CDECL ANDROID_WindowPosChanging( HWND hwnd, HWND insert_after, UINT swp_flags,
const RECT *window_rect, const RECT *client_rect, RECT *visible_rect, const RECT *window_rect, const RECT *client_rect, RECT *visible_rect,
struct window_surface **surface ) struct window_surface **surface )
{ {
struct android_win_data *data = get_win_data( hwnd ); struct android_win_data *data = get_win_data( hwnd );
RECT surface_rect; RECT surface_rect;
...@@ -1306,7 +1306,7 @@ void CDECL ANDROID_WindowPosChanging( HWND hwnd, HWND insert_after, UINT swp_fla ...@@ -1306,7 +1306,7 @@ void CDECL ANDROID_WindowPosChanging( HWND hwnd, HWND insert_after, UINT swp_fla
hwnd, wine_dbgstr_rect(window_rect), wine_dbgstr_rect(client_rect), hwnd, wine_dbgstr_rect(window_rect), wine_dbgstr_rect(client_rect),
GetWindowLongW( hwnd, GWL_STYLE ), swp_flags ); 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; *visible_rect = *window_rect;
...@@ -1339,6 +1339,7 @@ void CDECL ANDROID_WindowPosChanging( HWND hwnd, HWND insert_after, UINT swp_fla ...@@ -1339,6 +1339,7 @@ void CDECL ANDROID_WindowPosChanging( HWND hwnd, HWND insert_after, UINT swp_fla
done: done:
release_win_data( data ); release_win_data( data );
return TRUE;
} }
......
...@@ -2052,7 +2052,7 @@ static inline RECT get_surface_rect(const RECT *visible_rect) ...@@ -2052,7 +2052,7 @@ static inline RECT get_surface_rect(const RECT *visible_rect)
/*********************************************************************** /***********************************************************************
* WindowPosChanging (MACDRV.@) * 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, const RECT *window_rect, const RECT *client_rect,
RECT *visible_rect, struct window_surface **surface) RECT *visible_rect, struct window_surface **surface)
{ {
...@@ -2064,7 +2064,7 @@ void CDECL macdrv_WindowPosChanging(HWND hwnd, HWND insert_after, UINT swp_flags ...@@ -2064,7 +2064,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), swp_flags, wine_dbgstr_rect(window_rect), wine_dbgstr_rect(client_rect),
wine_dbgstr_rect(visible_rect), surface); 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; *visible_rect = *window_rect;
macdrv_window_to_mac_rect(data, style, visible_rect, window_rect, client_rect); macdrv_window_to_mac_rect(data, style, visible_rect, window_rect, client_rect);
...@@ -2097,6 +2097,7 @@ void CDECL macdrv_WindowPosChanging(HWND hwnd, HWND insert_after, UINT swp_flags ...@@ -2097,6 +2097,7 @@ void CDECL macdrv_WindowPosChanging(HWND hwnd, HWND insert_after, UINT swp_flags
done: done:
release_win_data(data); release_win_data(data);
return TRUE;
} }
......
...@@ -2318,7 +2318,7 @@ static inline BOOL get_surface_rect( const RECT *visible_rect, RECT *surface_rec ...@@ -2318,7 +2318,7 @@ static inline BOOL get_surface_rect( const RECT *visible_rect, RECT *surface_rec
/*********************************************************************** /***********************************************************************
* WindowPosChanging (X11DRV.@) * 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, const RECT *window_rect, const RECT *client_rect, RECT *visible_rect,
struct window_surface **surface ) struct window_surface **surface )
{ {
...@@ -2328,7 +2328,7 @@ void CDECL X11DRV_WindowPosChanging( HWND hwnd, HWND insert_after, UINT swp_flag ...@@ -2328,7 +2328,7 @@ void CDECL X11DRV_WindowPosChanging( HWND hwnd, HWND insert_after, UINT swp_flag
COLORREF key; COLORREF key;
BOOL layered = GetWindowLongW( hwnd, GWL_EXSTYLE ) & WS_EX_LAYERED; 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 */ /* check if we need to switch the window to managed */
if (!data->managed && data->whole_window && is_window_managed( hwnd, swp_flags, window_rect )) 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 ...@@ -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 ); TRACE( "making win %p/%lx managed\n", hwnd, data->whole_window );
release_win_data( data ); release_win_data( data );
unmap_window( hwnd ); unmap_window( hwnd );
if (!(data = get_win_data( hwnd ))) return; if (!(data = get_win_data( hwnd ))) return TRUE;
data->managed = TRUE; data->managed = TRUE;
} }
...@@ -2377,6 +2377,7 @@ void CDECL X11DRV_WindowPosChanging( HWND hwnd, HWND insert_after, UINT swp_flag ...@@ -2377,6 +2377,7 @@ void CDECL X11DRV_WindowPosChanging( HWND hwnd, HWND insert_after, UINT swp_flag
done: done:
release_win_data( data ); release_win_data( data );
return TRUE;
} }
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment