user32: Add support for managing a DIB surface for a window.

This commit is contained in:
Alexandre Julliard 2012-09-06 12:32:52 +02:00
parent 27b0b88a0b
commit a5ef549c6e
8 changed files with 121 additions and 20 deletions

View File

@ -420,13 +420,14 @@ static LRESULT CDECL nulldrv_WindowMessage( HWND hwnd, UINT msg, WPARAM wparam,
static void CDECL nulldrv_WindowPosChanging( HWND hwnd, HWND insert_after, UINT swp_flags,
const RECT *window_rect, const RECT *client_rect,
RECT *visible_rect )
RECT *visible_rect, struct window_surface **surface )
{
}
static void CDECL nulldrv_WindowPosChanged( HWND hwnd, HWND insert_after, UINT swp_flags,
const RECT *window_rect, const RECT *client_rect,
const RECT *visible_rect, const RECT *valid_rects )
const RECT *visible_rect, const RECT *valid_rects,
struct window_surface *surface )
{
}
@ -763,18 +764,19 @@ static LRESULT CDECL loaderdrv_WindowMessage( HWND hwnd, UINT msg, WPARAM wparam
static void CDECL loaderdrv_WindowPosChanging( HWND hwnd, HWND insert_after, UINT swp_flags,
const RECT *window_rect, const RECT *client_rect,
RECT *visible_rect )
RECT *visible_rect, struct window_surface **surface )
{
load_driver()->pWindowPosChanging( hwnd, insert_after, swp_flags,
window_rect, client_rect, visible_rect );
window_rect, client_rect, visible_rect, surface );
}
static void CDECL loaderdrv_WindowPosChanged( HWND hwnd, HWND insert_after, UINT swp_flags,
const RECT *window_rect, const RECT *client_rect,
const RECT *visible_rect, const RECT *valid_rects )
const RECT *visible_rect, const RECT *valid_rects,
struct window_surface *surface )
{
load_driver()->pWindowPosChanged( hwnd, insert_after, swp_flags, window_rect,
client_rect, visible_rect, valid_rects );
client_rect, visible_rect, valid_rects, surface );
}
static USER_DRIVER lazy_load_driver =

View File

@ -108,12 +108,14 @@ static void dump_rdw_flags(UINT flags)
*/
static void update_visible_region( struct dce *dce )
{
struct window_surface *surface = NULL;
NTSTATUS status;
HRGN vis_rgn = 0;
HWND top_win = 0;
DWORD flags = dce->flags;
size_t size = 256;
RECT win_rect, top_rect;
WND *win;
/* don't clip siblings if using parent clip region */
if (flags & DCX_PARENTCLIP) flags &= ~DCX_CLIPSIBLINGS;
@ -161,8 +163,16 @@ static void update_visible_region( struct dce *dce )
if (dce->clip_rgn) CombineRgn( vis_rgn, vis_rgn, dce->clip_rgn,
(flags & DCX_INTERSECTRGN) ? RGN_AND : RGN_DIFF );
top_rect = get_virtual_screen_rect();
__wine_set_visible_region( dce->hdc, vis_rgn, &win_rect, &top_rect, NULL );
if ((win = WIN_GetPtr( top_win )) && win != WND_DESKTOP && win != WND_OTHER_PROCESS)
{
surface = win->surface;
if (surface) window_surface_add_ref( surface );
WIN_ReleasePtr( win );
}
if (!surface) top_rect = get_virtual_screen_rect();
__wine_set_visible_region( dce->hdc, vis_rgn, &win_rect, &top_rect, surface );
if (surface) window_surface_release( surface );
}
@ -181,8 +191,12 @@ static void reset_dce_attrs( struct dce *dce )
*/
static void release_dce( struct dce *dce )
{
RECT vis_rect;
if (!dce->hwnd) return; /* already released */
vis_rect = get_virtual_screen_rect();
__wine_set_visible_region( dce->hdc, 0, &vis_rect, &vis_rect, NULL );
USER_Driver->pReleaseDC( dce->hwnd, dce->hdc );
if (dce->clip_rgn) DeleteObject( dce->clip_rgn );
@ -743,6 +757,46 @@ void erase_now( HWND hwnd, UINT rdw_flags )
}
/***********************************************************************
* move_window_bits
*
* Move the window bits when a window is resized or its surface recreated.
*/
void move_window_bits( HWND hwnd, struct window_surface *old_surface,
struct window_surface *new_surface,
const RECT *visible_rect, const RECT *old_visible_rect,
const RECT *client_rect, const RECT *valid_rects )
{
RECT dst = valid_rects[0];
RECT src = valid_rects[1];
if (new_surface != old_surface ||
src.left - old_visible_rect->left != dst.left - visible_rect->left ||
src.top - old_visible_rect->top != dst.top - visible_rect->top)
{
char buffer[FIELD_OFFSET( BITMAPINFO, bmiColors[256] )];
BITMAPINFO *info = (BITMAPINFO *)buffer;
void *bits;
UINT flags = UPDATE_NOCHILDREN;
HRGN rgn = get_update_region( hwnd, &flags, NULL );
HDC hdc = GetDCEx( hwnd, rgn, DCX_CACHE | DCX_EXCLUDERGN );
OffsetRect( &dst, -client_rect->left, -client_rect->top );
TRACE( "copying %s -> %s\n", wine_dbgstr_rect(&src), wine_dbgstr_rect(&dst) );
bits = old_surface->funcs->get_info( old_surface, info );
old_surface->funcs->lock( old_surface );
SetDIBitsToDevice( hdc, dst.left, dst.top, dst.right - dst.left, dst.bottom - dst.top,
src.left - old_visible_rect->left - old_surface->rect.left,
old_surface->rect.bottom - (src.bottom - old_visible_rect->top),
0, old_surface->rect.bottom - old_surface->rect.top,
bits, info, DIB_RGB_COLORS );
old_surface->funcs->unlock( old_surface );
ReleaseDC( hwnd, hdc );
DeleteObject( rgn );
}
}
/***********************************************************************
* update_now
*

View File

@ -35,6 +35,8 @@
#define WM_SYSTIMER 0x0118
#define WM_POPUPSYSTEMMENU 0x0313
struct window_surface;
/* internal messages codes */
enum wine_internal_message
{
@ -110,8 +112,8 @@ typedef struct tagUSER_DRIVER {
UINT (CDECL *pShowWindow)(HWND,INT,RECT*,UINT);
LRESULT (CDECL *pSysCommand)(HWND,WPARAM,LPARAM);
LRESULT (CDECL *pWindowMessage)(HWND,UINT,WPARAM,LPARAM);
void (CDECL *pWindowPosChanging)(HWND,HWND,UINT,const RECT *,const RECT *,RECT *);
void (CDECL *pWindowPosChanged)(HWND,HWND,UINT,const RECT *,const RECT *,const RECT *,const RECT *);
void (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*);
} USER_DRIVER;
extern const USER_DRIVER *USER_Driver DECLSPEC_HIDDEN;
@ -213,6 +215,10 @@ extern BOOL set_capture_window( HWND hwnd, UINT gui_flags, HWND *prev_ret ) DECL
extern void free_dce( struct dce *dce, HWND hwnd ) DECLSPEC_HIDDEN;
extern void invalidate_dce( struct tagWND *win, const RECT *rect ) DECLSPEC_HIDDEN;
extern void erase_now( HWND hwnd, UINT rdw_flags ) DECLSPEC_HIDDEN;
extern void move_window_bits( HWND hwnd, struct window_surface *old_surface,
struct window_surface *new_surface,
const RECT *visible_rect, const RECT *old_visible_rect,
const RECT *client_rect, const RECT *valid_rects ) DECLSPEC_HIDDEN;
extern void *get_hook_proc( void *proc, const WCHAR *module ) DECLSPEC_HIDDEN;
extern RECT get_virtual_screen_rect(void) DECLSPEC_HIDDEN;
extern LRESULT call_current_hook( HHOOK hhook, INT code, WPARAM wparam, LPARAM lparam ) DECLSPEC_HIDDEN;

View File

@ -34,6 +34,7 @@
#include "user_private.h"
#include "controls.h"
#include "winerror.h"
#include "wine/gdi_driver.h"
#include "wine/debug.h"
WINE_DEFAULT_DEBUG_CHANNEL(win);
@ -810,6 +811,7 @@ LRESULT WIN_DestroyWindow( HWND hwnd )
HWND *list;
HMENU menu = 0, sys_menu;
HWND icon_title;
struct window_surface *surface;
TRACE("%p\n", hwnd );
@ -854,11 +856,14 @@ LRESULT WIN_DestroyWindow( HWND hwnd )
wndPtr->text = NULL;
HeapFree( GetProcessHeap(), 0, wndPtr->pScroll );
wndPtr->pScroll = NULL;
surface = wndPtr->surface;
wndPtr->surface = NULL;
WIN_ReleasePtr( wndPtr );
if (icon_title) DestroyWindow( icon_title );
if (menu) DestroyMenu( menu );
if (sys_menu) DestroyMenu( sys_menu );
if (surface) window_surface_release( surface );
USER_Driver->pDestroyWindow( hwnd );
@ -877,6 +882,7 @@ static void destroy_thread_window( HWND hwnd )
WND *wndPtr;
HWND *list;
HMENU menu = 0, sys_menu = 0;
struct window_surface *surface = NULL;
WORD index;
/* free child windows */
@ -902,6 +908,8 @@ static void destroy_thread_window( HWND hwnd )
if ((wndPtr->dwStyle & (WS_CHILD | WS_POPUP)) != WS_CHILD) menu = (HMENU)wndPtr->wIDmenu;
sys_menu = wndPtr->hSysMenu;
free_dce( wndPtr->dce, hwnd );
surface = wndPtr->surface;
wndPtr->surface = NULL;
InterlockedCompareExchangePointer( &user_handles[index], NULL, wndPtr );
}
USER_Unlock();
@ -909,6 +917,7 @@ static void destroy_thread_window( HWND hwnd )
HeapFree( GetProcessHeap(), 0, wndPtr );
if (menu) DestroyMenu( menu );
if (sys_menu) DestroyMenu( sys_menu );
if (surface) window_surface_release( surface );
}

View File

@ -45,6 +45,7 @@ typedef struct tagWND
HINSTANCE hInstance; /* Window hInstance (from CreateWindow) */
RECT rectClient; /* Client area rel. to parent client area */
RECT rectWindow; /* Whole window rel. to parent client area */
RECT visible_rect; /* Visible part of the whole rect, rel. to parent client area */
RECT normal_rect; /* Normal window rect saved when maximized/minimized */
POINT min_pos; /* Position for minimized window */
POINT max_pos; /* Position for maximized window */
@ -59,6 +60,7 @@ typedef struct tagWND
HMENU hSysMenu; /* window's copy of System Menu */
HICON hIcon; /* window's icon */
HICON hIconSmall; /* window's small icon */
struct window_surface *surface; /* Window surface if any */
struct tagDIALOGINFO *dlgInfo;/* Dialog additional info (dialogs only) */
int cbWndExtra; /* class cbWndExtra at window creation */
DWORD_PTR userdata; /* User private data */

View File

@ -33,6 +33,7 @@
#include "wine/server.h"
#include "controls.h"
#include "user_private.h"
#include "wine/gdi_driver.h"
#include "win.h"
#include "wine/debug.h"
@ -1949,18 +1950,23 @@ BOOL set_window_pos( HWND hwnd, HWND insert_after, UINT swp_flags,
{
WND *win;
BOOL ret;
RECT visible_rect, old_window_rect;
int old_width;
RECT visible_rect, old_visible_rect, old_window_rect;
struct window_surface *old_surface, *new_surface = NULL;
visible_rect = *window_rect;
USER_Driver->pWindowPosChanging( hwnd, insert_after, swp_flags,
window_rect, client_rect, &visible_rect );
window_rect, client_rect, &visible_rect, &new_surface );
WIN_GetRectangles( hwnd, COORDS_SCREEN, &old_window_rect, NULL );
if (!(win = WIN_GetPtr( hwnd ))) return FALSE;
if (win == WND_DESKTOP || win == WND_OTHER_PROCESS) return FALSE;
if (!(win = WIN_GetPtr( hwnd )) || win == WND_DESKTOP || win == WND_OTHER_PROCESS)
{
if (new_surface) window_surface_release( new_surface );
return FALSE;
}
old_width = win->rectClient.right - win->rectClient.left;
old_visible_rect = win->visible_rect;
SERVER_START_REQ( set_window_pos )
{
@ -1987,12 +1993,16 @@ BOOL set_window_pos( HWND hwnd, HWND insert_after, UINT swp_flags,
win->dwExStyle = reply->new_ex_style;
win->rectWindow = *window_rect;
win->rectClient = *client_rect;
win->visible_rect = visible_rect;
old_surface = win->surface;
win->surface = new_surface;
if (GetWindowLongW( win->parent, GWL_EXSTYLE ) & WS_EX_LAYOUTRTL)
{
RECT client;
GetClientRect( win->parent, &client );
mirror_rect( &client, &win->rectWindow );
mirror_rect( &client, &win->rectClient );
mirror_rect( &client, &win->visible_rect );
}
/* if an RTL window is resized the children have moved */
if (win->dwExStyle & WS_EX_LAYOUTRTL && client_rect->right - client_rect->left != old_width)
@ -2007,8 +2017,24 @@ BOOL set_window_pos( HWND hwnd, HWND insert_after, UINT swp_flags,
WIN_ReleasePtr( win );
if (ret) USER_Driver->pWindowPosChanged( hwnd, insert_after, swp_flags, window_rect,
client_rect, &visible_rect, valid_rects );
if (ret)
{
TRACE( "win %p surface %p -> %p\n", hwnd, old_surface, new_surface );
if (old_surface)
{
if (!IsRectEmpty( valid_rects ))
{
move_window_bits( hwnd, old_surface, new_surface, &visible_rect,
&old_visible_rect, client_rect, valid_rects );
valid_rects = NULL; /* prevent the driver from trying to also move the bits */
}
window_surface_release( old_surface );
}
USER_Driver->pWindowPosChanged( hwnd, insert_after, swp_flags, window_rect,
client_rect, &visible_rect, valid_rects, new_surface );
}
else if (new_surface) window_surface_release( new_surface );
return ret;
}

View File

@ -2010,7 +2010,8 @@ void CDECL X11DRV_SetFocus( HWND hwnd )
* WindowPosChanging (X11DRV.@)
*/
void 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 x11drv_win_data *data = X11DRV_get_win_data( hwnd );
@ -2035,7 +2036,8 @@ void CDECL X11DRV_WindowPosChanging( HWND hwnd, HWND insert_after, UINT swp_flag
*/
void CDECL X11DRV_WindowPosChanged( HWND hwnd, HWND insert_after, UINT swp_flags,
const RECT *rectWindow, const RECT *rectClient,
const RECT *visible_rect, const RECT *valid_rects )
const RECT *visible_rect, const RECT *valid_rects,
struct window_surface *surface )
{
struct x11drv_thread_data *thread_data;
Display *display;

View File

@ -52,8 +52,8 @@
@ cdecl ShowWindow(long long ptr long) X11DRV_ShowWindow
@ cdecl SysCommand(long long long) X11DRV_SysCommand
@ cdecl WindowMessage(long long long long) X11DRV_WindowMessage
@ cdecl WindowPosChanging(long long long ptr ptr ptr) X11DRV_WindowPosChanging
@ cdecl WindowPosChanged(long long long ptr ptr ptr ptr) X11DRV_WindowPosChanged
@ cdecl WindowPosChanging(long long long ptr ptr ptr ptr) X11DRV_WindowPosChanging
@ cdecl WindowPosChanged(long long long ptr ptr ptr ptr ptr) X11DRV_WindowPosChanged
# WinTab32
@ cdecl AttachEventQueueToTablet(long) X11DRV_AttachEventQueueToTablet