user32: factorize graphics driver's CreateWindow [take 2]
Pierre d'Herbemont
pdherbemont at free.fr
Tue Dec 12 18:30:29 CST 2006
This time without WND use in the driver.
We use two extra parameters client_rect and window_rect in drivers'
CreateWindow, because there seems to be no good way to retrieve real
window client rect using Win32 API.
Also I suggest to try to run `make test`. Some tests don't pass here
with a clean git wine, probably because of a broken X.org version.
However this patch doesn't seem to introduce new failure here.
Pierre.
---
dlls/user32/driver.c | 8 +-
dlls/user32/user_private.h | 2 +-
dlls/user32/win.c | 131 ++++++++++++++++++++++++++++++++-
dlls/winex11.drv/window.c | 148
++++---------------------------------
dlls/winex11.drv/winex11.drv.spec | 2 +-
dlls/winex11.drv/winpos.c | 26 +++++--
dlls/winex11.drv/x11drv.h | 2 +-
7 files changed, 173 insertions(+), 146 deletions(-)
-------------- next part --------------
diff --git a/dlls/user32/driver.c b/dlls/user32/driver.c
index 0c93a67..50d4dbc 100644
--- a/dlls/user32/driver.c
+++ b/dlls/user32/driver.c
@@ -312,7 +312,8 @@ static BOOL nulldrv_CreateDesktopWindow(
return TRUE;
}
-static BOOL nulldrv_CreateWindow( HWND hwnd, CREATESTRUCTA *cs, BOOL unicode )
+static BOOL nulldrv_CreateWindow( HWND hwnd, CREATESTRUCTA *cs, const RECT *window_rect,
+ const RECT *client_rect )
{
static int warned;
if (warned++)
@@ -646,9 +647,10 @@ static BOOL loaderdrv_CreateDesktopWindo
return load_driver()->pCreateDesktopWindow( hwnd );
}
-static BOOL loaderdrv_CreateWindow( HWND hwnd, CREATESTRUCTA *cs, BOOL unicode )
+static BOOL loaderdrv_CreateWindow( HWND hwnd, CREATESTRUCTA *cs, const RECT *window_rect,
+ const RECT *client_rect )
{
- return load_driver()->pCreateWindow( hwnd, cs, unicode );
+ return load_driver()->pCreateWindow( hwnd, cs, window_rect, client_rect );
}
static void loaderdrv_DestroyWindow( HWND hwnd )
diff --git a/dlls/user32/user_private.h b/dlls/user32/user_private.h
index ae27884..a95d983 100644
--- a/dlls/user32/user_private.h
+++ b/dlls/user32/user_private.h
@@ -141,7 +141,7 @@ typedef struct tagUSER_DRIVER {
BOOL (*pGetMonitorInfo)(HMONITOR,MONITORINFO*);
/* windowing functions */
BOOL (*pCreateDesktopWindow)(HWND);
- BOOL (*pCreateWindow)(HWND,CREATESTRUCTA*,BOOL);
+ BOOL (*pCreateWindow)(HWND,CREATESTRUCTA*,const RECT *, const RECT *);
void (*pDestroyWindow)(HWND);
HDC (*pGetDCEx)(HWND,HRGN,DWORD);
DWORD (*pMsgWaitForMultipleObjectsEx)(DWORD,const HANDLE*,DWORD,DWORD,DWORD);
diff --git a/dlls/user32/win.c b/dlls/user32/win.c
index 42b7696..26b111b 100644
--- a/dlls/user32/win.c
+++ b/dlls/user32/win.c
@@ -865,6 +865,12 @@ static HWND WIN_CreateWindowEx( CREATEST
HWND hwnd, parent, owner, top_child = 0;
BOOL unicode = (flags & WIN_ISUNICODE) != 0;
MDICREATESTRUCTA mdi_cs;
+ RECT client_rect, window_rect;
+ HWND insert_after;
+ RECT rect;
+ CBT_CREATEWNDA cbtc;
+ CREATESTRUCTA cbcs;
+ BOOL ret = FALSE;
TRACE("%s %s ex=%08x style=%08x %d,%d %dx%d parent=%p menu=%p inst=%p params=%p\n",
unicode ? debugstr_w((LPCWSTR)cs->lpszName) : debugstr_a(cs->lpszName),
@@ -1077,7 +1083,130 @@ static HWND WIN_CreateWindowEx( CREATEST
else SetWindowLongPtrW( hwnd, GWLP_ID, (ULONG_PTR)cs->hMenu );
WIN_ReleasePtr( wndPtr );
- if (!USER_Driver->pCreateWindow( hwnd, cs, unicode))
+ if (cs->cx > 65535)
+ {
+ ERR( "invalid window width %d\n", cs->cx );
+ cs->cx = 65535;
+ }
+ if (cs->cy > 65535)
+ {
+ ERR( "invalid window height %d\n", cs->cy );
+ cs->cy = 65535;
+ }
+ if (cs->cx < 0)
+ {
+ ERR( "invalid window width %d\n", cs->cx );
+ cs->cx = 0;
+ }
+ if (cs->cy < 0)
+ {
+ ERR( "invalid window height %d\n", cs->cy );
+ cs->cy = 0;
+ }
+
+ /* initialize the dimensions before sending WM_GETMINMAXINFO */
+ SetRect( &rect, cs->x, cs->y, cs->x + cs->cx, cs->y + cs->cy );
+ USER_Driver->pSetWindowPos( hwnd, 0, &rect, &rect, SWP_NOZORDER, NULL );
+
+ /* Call the WH_CBT hook */
+
+ /* the window style passed to the hook must be the real window style,
+ * rather than just the window style that the caller to CreateWindowEx
+ * passed in, so we have to copy the original CREATESTRUCT and get the
+ * the real style. */
+ cbcs = *cs;
+ cbcs.style = GetWindowLongW(hwnd, GWL_STYLE);
+
+ cbtc.lpcs = &cbcs;
+ cbtc.hwndInsertAfter = HWND_TOP;
+ if (HOOK_CallHooks( WH_CBT, HCBT_CREATEWND, (WPARAM)hwnd, (LPARAM)&cbtc, unicode ))
+ {
+ TRACE("CBT-hook returned !0\n");
+ return 0;
+ }
+
+ /* Send the WM_GETMINMAXINFO message and fix the size if needed */
+ if ((cs->style & WS_THICKFRAME) || !(cs->style & (WS_POPUP | WS_CHILD)))
+ {
+ POINT maxSize, maxPos, minTrack, maxTrack;
+
+ WINPOS_GetMinMaxInfo( hwnd, &maxSize, &maxPos, &minTrack, &maxTrack);
+ if (maxSize.x < cs->cx) cs->cx = maxSize.x;
+ if (maxSize.y < cs->cy) cs->cy = maxSize.y;
+ if (cs->cx < 0) cs->cx = 0;
+ if (cs->cy < 0) cs->cy = 0;
+
+ SetRect( &rect, cs->x, cs->y, cs->x + cs->cx, cs->y + cs->cy );
+ if (!USER_Driver->pSetWindowPos( hwnd, 0, &rect, &rect, SWP_NOZORDER, NULL )) return FALSE;
+ }
+
+ /* send WM_NCCREATE */
+ TRACE( "hwnd %p cs %d,%d %dx%d\n", hwnd, cs->x, cs->y, cs->cx, cs->cy );
+ if (unicode)
+ ret = SendMessageW( hwnd, WM_NCCREATE, 0, (LPARAM)cs );
+ else
+ ret = SendMessageA( hwnd, WM_NCCREATE, 0, (LPARAM)cs );
+ if (!ret)
+ {
+ WARN("aborted by WM_xxCREATE!\n");
+ return FALSE;
+ }
+
+ if (!(wndPtr = WIN_GetPtr(hwnd))) return 0;
+
+ /* send WM_NCCALCSIZE */
+ rect = wndPtr->rectWindow;
+ WIN_ReleasePtr( wndPtr );
+
+ SendMessageW( hwnd, WM_NCCALCSIZE, FALSE, (LPARAM)&rect );
+
+ /* yes, even if the CBT hook was called with HWND_TOP */
+ if (!(wndPtr = WIN_GetPtr(hwnd))) return 0;
+
+ insert_after = ((wndPtr->dwStyle & (WS_CHILD|WS_MAXIMIZE)) == WS_CHILD) ? HWND_BOTTOM : HWND_TOP;
+
+ USER_Driver->pSetWindowPos( hwnd, insert_after, &wndPtr->rectWindow, &rect, 0, NULL );
+
+ TRACE( "win %p window %d,%d,%d,%d client %d,%d,%d,%d\n",
+ hwnd, wndPtr->rectWindow.left, wndPtr->rectWindow.top,
+ wndPtr->rectWindow.right, wndPtr->rectWindow.bottom,
+ wndPtr->rectClient.left, wndPtr->rectClient.top,
+ wndPtr->rectClient.right, wndPtr->rectClient.bottom);
+
+ WIN_ReleasePtr( wndPtr );
+
+ if (unicode)
+ ret = (SendMessageW( hwnd, WM_CREATE, 0, (LPARAM)cs ) != -1);
+ else
+ ret = (SendMessageA( hwnd, WM_CREATE, 0, (LPARAM)cs ) != -1);
+
+ if (!ret) return FALSE;
+
+ NotifyWinEvent(EVENT_OBJECT_CREATE, hwnd, OBJID_WINDOW, 0);
+
+ /* Send the size messages */
+
+ if (!(wndPtr = WIN_GetPtr(hwnd)) || wndPtr == WND_OTHER_PROCESS) return FALSE;
+ if (!(wndPtr->flags & WIN_NEED_SIZE))
+ {
+ RECT rect = wndPtr->rectClient;
+ WIN_ReleasePtr( wndPtr );
+ /* send it anyway */
+ if (((rect.right-rect.left) <0) ||((rect.bottom-rect.top)<0))
+ WARN("sending bogus WM_SIZE message 0x%08x\n",
+ MAKELONG(rect.right-rect.left, rect.bottom-rect.top));
+ SendMessageW( hwnd, WM_SIZE, SIZE_RESTORED,
+ MAKELONG(rect.right-rect.left, rect.bottom-rect.top));
+ SendMessageW( hwnd, WM_MOVE, 0, MAKELONG( rect.left, rect.top ) );
+ }
+ else WIN_ReleasePtr( wndPtr );
+
+ if (!(wndPtr = WIN_GetPtr(hwnd)) || wndPtr == WND_OTHER_PROCESS) return FALSE;
+ client_rect = wndPtr->rectClient;
+ window_rect = wndPtr->rectWindow;
+ WIN_ReleasePtr( wndPtr );
+
+ if (!USER_Driver->pCreateWindow( hwnd, cs, &window_rect, &client_rect))
{
WIN_DestroyWindow( hwnd );
return 0;
diff --git a/dlls/winex11.drv/window.c b/dlls/winex11.drv/window.c
index 26bd8e1..b8ebe2f 100644
--- a/dlls/winex11.drv/window.c
+++ b/dlls/winex11.drv/window.c
@@ -634,17 +634,17 @@ void X11DRV_set_iconic_state( HWND hwnd
*
* Convert a rect from client to X window coordinates
*/
-void X11DRV_window_to_X_rect( struct x11drv_win_data *data, RECT *rect )
+void X11DRV_window_to_X_rect( HWND hwnd, RECT *rect )
{
RECT rc;
- if (!data->managed) return;
+ if (!is_window_managed(hwnd)) return;
if (IsRectEmpty( rect )) return;
rc.top = rc.bottom = rc.left = rc.right = 0;
- AdjustWindowRectEx( &rc, GetWindowLongW( data->hwnd, GWL_STYLE ) & ~(WS_HSCROLL|WS_VSCROLL),
- FALSE, GetWindowLongW( data->hwnd, GWL_EXSTYLE ) );
+ AdjustWindowRectEx( &rc, GetWindowLongW( hwnd, GWL_STYLE ) & ~(WS_HSCROLL|WS_VSCROLL),
+ FALSE, GetWindowLongW( hwnd, GWL_EXSTYLE ) );
rect->left -= rc.left;
rect->right -= rc.right;
@@ -756,7 +756,7 @@ static Window create_whole_window( Displ
RECT rect;
rect = data->window_rect;
- X11DRV_window_to_X_rect( data, &rect );
+ X11DRV_window_to_X_rect( data->hwnd, &rect );
if (!(cx = rect.right - rect.left)) cx = 1;
if (!(cy = rect.bottom - rect.top)) cy = 1;
@@ -1002,44 +1002,18 @@ BOOL X11DRV_CreateDesktopWindow( HWND hw
/**********************************************************************
* CreateWindow (X11DRV.@)
*/
-BOOL X11DRV_CreateWindow( HWND hwnd, CREATESTRUCTA *cs, BOOL unicode )
+BOOL X11DRV_CreateWindow( HWND hwnd, CREATESTRUCTA *cs, const RECT *window_rect, const RECT *client_rect )
{
Display *display = thread_display();
- WND *wndPtr;
struct x11drv_win_data *data;
- HWND insert_after;
- RECT rect;
+ LPWSTR text;
DWORD style;
- CBT_CREATEWNDA cbtc;
- CREATESTRUCTA cbcs;
- BOOL ret = FALSE;
+ int text_size;
if (!(data = alloc_win_data( display, hwnd ))) return FALSE;
- if (cs->cx > 65535)
- {
- ERR( "invalid window width %d\n", cs->cx );
- cs->cx = 65535;
- }
- if (cs->cy > 65535)
- {
- ERR( "invalid window height %d\n", cs->cy );
- cs->cy = 65535;
- }
- if (cs->cx < 0)
- {
- ERR( "invalid window width %d\n", cs->cx );
- cs->cx = 0;
- }
- if (cs->cy < 0)
- {
- ERR( "invalid window height %d\n", cs->cy );
- cs->cy = 0;
- }
-
- /* initialize the dimensions before sending WM_GETMINMAXINFO */
- SetRect( &rect, cs->x, cs->y, cs->x + cs->cx, cs->y + cs->cy );
- X11DRV_SetWindowPos( hwnd, 0, &rect, &rect, SWP_NOZORDER, NULL );
+ /* initialize the win data dimensions before calling create_whole_window/get_desktop_xwin */
+ X11DRV_SetWindowPos( hwnd, 0, window_rect, client_rect, SWP_NOZORDER, NULL );
/* create an X window if it's a top level window */
if (GetAncestor( hwnd, GA_PARENT ) == GetDesktopWindow())
@@ -1054,106 +1028,16 @@ BOOL X11DRV_CreateWindow( HWND hwnd, CRE
/* get class or window DC if needed */
alloc_window_dce( data );
- /* Call the WH_CBT hook */
-
- /* the window style passed to the hook must be the real window style,
- * rather than just the window style that the caller to CreateWindowEx
- * passed in, so we have to copy the original CREATESTRUCT and get the
- * the real style. */
- cbcs = *cs;
- cbcs.style = GetWindowLongW(hwnd, GWL_STYLE);
-
- cbtc.lpcs = &cbcs;
- cbtc.hwndInsertAfter = HWND_TOP;
- if (HOOK_CallHooks( WH_CBT, HCBT_CREATEWND, (WPARAM)hwnd, (LPARAM)&cbtc, unicode ))
- {
- TRACE("CBT-hook returned !0\n");
- goto failed;
- }
-
- /* Send the WM_GETMINMAXINFO message and fix the size if needed */
- if ((cs->style & WS_THICKFRAME) || !(cs->style & (WS_POPUP | WS_CHILD)))
- {
- POINT maxSize, maxPos, minTrack, maxTrack;
-
- WINPOS_GetMinMaxInfo( hwnd, &maxSize, &maxPos, &minTrack, &maxTrack);
- if (maxSize.x < cs->cx) cs->cx = maxSize.x;
- if (maxSize.y < cs->cy) cs->cy = maxSize.y;
- if (cs->cx < 0) cs->cx = 0;
- if (cs->cy < 0) cs->cy = 0;
-
- SetRect( &rect, cs->x, cs->y, cs->x + cs->cx, cs->y + cs->cy );
- if (!X11DRV_SetWindowPos( hwnd, 0, &rect, &rect, SWP_NOZORDER, NULL )) return FALSE;
- }
-
- /* send WM_NCCREATE */
- TRACE( "hwnd %p cs %d,%d %dx%d\n", hwnd, cs->x, cs->y, cs->cx, cs->cy );
- if (unicode)
- ret = SendMessageW( hwnd, WM_NCCREATE, 0, (LPARAM)cs );
- else
- ret = SendMessageA( hwnd, WM_NCCREATE, 0, (LPARAM)cs );
- if (!ret)
- {
- WARN("aborted by WM_xxCREATE!\n");
- return FALSE;
- }
-
- /* make sure the window is still valid */
- if (!(data = X11DRV_get_win_data( hwnd ))) return FALSE;
- if (data->whole_window) X11DRV_sync_window_style( display, data );
-
- /* send WM_NCCALCSIZE */
- rect = data->window_rect;
- SendMessageW( hwnd, WM_NCCALCSIZE, FALSE, (LPARAM)&rect );
-
- if (!(wndPtr = WIN_GetPtr(hwnd))) return FALSE;
-
- /* yes, even if the CBT hook was called with HWND_TOP */
- insert_after = ((wndPtr->dwStyle & (WS_CHILD|WS_MAXIMIZE)) == WS_CHILD) ? HWND_BOTTOM : HWND_TOP;
-
- X11DRV_SetWindowPos( hwnd, insert_after, &wndPtr->rectWindow, &rect, 0, NULL );
-
- TRACE( "win %p window %d,%d,%d,%d client %d,%d,%d,%d whole %d,%d,%d,%d X client %d,%d,%d,%d xwin %x\n",
- hwnd, wndPtr->rectWindow.left, wndPtr->rectWindow.top,
- wndPtr->rectWindow.right, wndPtr->rectWindow.bottom,
- wndPtr->rectClient.left, wndPtr->rectClient.top,
- wndPtr->rectClient.right, wndPtr->rectClient.bottom,
- data->whole_rect.left, data->whole_rect.top,
- data->whole_rect.right, data->whole_rect.bottom,
- data->client_rect.left, data->client_rect.top,
- data->client_rect.right, data->client_rect.bottom,
- (unsigned int)data->whole_window );
-
- WIN_ReleasePtr( wndPtr );
-
- if (unicode)
- ret = (SendMessageW( hwnd, WM_CREATE, 0, (LPARAM)cs ) != -1);
- else
- ret = (SendMessageA( hwnd, WM_CREATE, 0, (LPARAM)cs ) != -1);
-
- if (!ret) return FALSE;
-
- NotifyWinEvent(EVENT_OBJECT_CREATE, hwnd, OBJID_WINDOW, 0);
-
- /* Send the size messages */
-
- if (!(wndPtr = WIN_GetPtr(hwnd)) || wndPtr == WND_OTHER_PROCESS) return FALSE;
- if (!(wndPtr->flags & WIN_NEED_SIZE))
+ /* Make sure we've updated the window title if SetWindowText was called
+ before alloc_win_data */
+ text_size = GetWindowTextLengthW( hwnd ) + 1;
+ if (text_size > 1 && (text = HeapAlloc( GetProcessHeap(), 0, text_size * sizeof(WCHAR) )))
{
- RECT rect = wndPtr->rectClient;
- WIN_ReleasePtr( wndPtr );
- /* send it anyway */
- if (((rect.right-rect.left) <0) ||((rect.bottom-rect.top)<0))
- WARN("sending bogus WM_SIZE message 0x%08x\n",
- MAKELONG(rect.right-rect.left, rect.bottom-rect.top));
- SendMessageW( hwnd, WM_SIZE, SIZE_RESTORED,
- MAKELONG(rect.right-rect.left, rect.bottom-rect.top));
- SendMessageW( hwnd, WM_MOVE, 0, MAKELONG( rect.left, rect.top ) );
+ if(GetWindowTextW( hwnd, text, text_size ))
+ X11DRV_SetWindowText( hwnd, text );
}
- else WIN_ReleasePtr( wndPtr );
/* Show the window, maximizing or minimizing if needed */
-
style = GetWindowLongW( hwnd, GWL_STYLE );
if (style & (WS_MINIMIZE | WS_MAXIMIZE))
{
diff --git a/dlls/winex11.drv/winex11.drv.spec b/dlls/winex11.drv/winex11.drv.spec
index 95b3d94..b487281 100644
--- a/dlls/winex11.drv/winex11.drv.spec
+++ b/dlls/winex11.drv/winex11.drv.spec
@@ -88,7 +88,7 @@
@ cdecl AcquireClipboard(long) X11DRV_AcquireClipboard
@ cdecl CountClipboardFormats() X11DRV_CountClipboardFormats
@ cdecl CreateDesktopWindow(long) X11DRV_CreateDesktopWindow
-@ cdecl CreateWindow(long ptr long) X11DRV_CreateWindow
+@ cdecl CreateWindow(long ptr ptr ptr) X11DRV_CreateWindow
@ cdecl DestroyWindow(long) X11DRV_DestroyWindow
@ cdecl EmptyClipboard(long) X11DRV_EmptyClipboard
@ cdecl EndClipboardUpdate() X11DRV_EndClipboardUpdate
diff --git a/dlls/winex11.drv/winpos.c b/dlls/winex11.drv/winpos.c
index 5a88a74..454d9ff 100644
--- a/dlls/winex11.drv/winpos.c
+++ b/dlls/winex11.drv/winpos.c
@@ -234,18 +234,19 @@ BOOL X11DRV_SetWindowPos( HWND hwnd, HWN
DWORD old_style, new_style;
BOOL ret;
- if (!(data = X11DRV_get_win_data( hwnd ))) return FALSE;
+ data = X11DRV_get_win_data( hwnd );
new_whole_rect = *rectWindow;
- X11DRV_window_to_X_rect( data, &new_whole_rect );
+ X11DRV_window_to_X_rect( hwnd, &new_whole_rect );
- old_client_rect = data->client_rect;
+ if(data)
+ old_client_rect = data->client_rect;
if (!IsRectEmpty( &valid_rects[0] ))
{
int x_offset = 0, y_offset = 0;
- if (data->whole_window)
+ if (data && data->whole_window)
{
/* the X server will move the bits for us */
x_offset = data->whole_rect.left - new_whole_rect.left;
@@ -258,6 +259,9 @@ BOOL X11DRV_SetWindowPos( HWND hwnd, HWN
/* FIXME: should copy the window bits here */
valid_rects = NULL;
}
+
+ if(!data)
+ valid_rects = NULL;
}
if (!(win = WIN_GetPtr( hwnd ))) return FALSE;
@@ -290,9 +294,10 @@ BOOL X11DRV_SetWindowPos( HWND hwnd, HWN
}
SERVER_END_REQ;
- if (win == WND_DESKTOP || data->whole_window == DefaultRootWindow(gdi_display))
+ if (win == WND_DESKTOP || (data && data->whole_window == DefaultRootWindow(gdi_display)) )
{
- data->whole_rect = data->client_rect = data->window_rect = *rectWindow;
+ if(data)
+ data->whole_rect = data->client_rect = data->window_rect = *rectWindow;
if (win != WND_DESKTOP)
{
win->rectWindow = *rectWindow;
@@ -321,11 +326,18 @@ BOOL X11DRV_SetWindowPos( HWND hwnd, HWN
win->rectClient = *rectClient;
old_style = win->dwStyle;
win->dwStyle = new_style;
- data->window_rect = *rectWindow;
TRACE( "win %p window %s client %s style %08x\n",
hwnd, wine_dbgstr_rect(rectWindow), wine_dbgstr_rect(rectClient), new_style );
+ if(!data)
+ {
+ WIN_ReleasePtr( win );
+ return ret;
+ }
+
+ data->window_rect = *rectWindow;
+
/* FIXME: copy the valid bits */
if (data->whole_window && !data->lock_changes)
diff --git a/dlls/winex11.drv/x11drv.h b/dlls/winex11.drv/x11drv.h
index c56d94d..63137bd 100644
--- a/dlls/winex11.drv/x11drv.h
+++ b/dlls/winex11.drv/x11drv.h
@@ -677,7 +677,7 @@ typedef int (*x11drv_error_callback)( Di
extern void X11DRV_expect_error( Display *display, x11drv_error_callback callback, void *arg );
extern int X11DRV_check_error(void);
extern void X11DRV_set_iconic_state( HWND hwnd );
-extern void X11DRV_window_to_X_rect( struct x11drv_win_data *data, RECT *rect );
+extern void X11DRV_window_to_X_rect( HWND hwnd, RECT *rect );
extern void X11DRV_X_to_window_rect( struct x11drv_win_data *data, RECT *rect );
extern void X11DRV_sync_window_style( Display *display, struct x11drv_win_data *data );
extern void X11DRV_sync_window_position( Display *display, struct x11drv_win_data *data,
More information about the wine-patches
mailing list