mirror of
https://github.com/reactos/wine.git
synced 2024-11-25 04:39:45 +00:00
user32: Add support for managing a DIB surface for a window.
This commit is contained in:
parent
27b0b88a0b
commit
a5ef549c6e
@ -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 =
|
||||
|
@ -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
|
||||
*
|
||||
|
@ -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;
|
||||
|
@ -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 );
|
||||
}
|
||||
|
||||
|
||||
|
@ -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 */
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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;
|
||||
|
@ -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
|
||||
|
Loading…
Reference in New Issue
Block a user