Fixed handling of zero-sized client window.

Create the X windows before sending WM_NCCREATE.
This commit is contained in:
Alexandre Julliard 2001-06-12 04:02:10 +00:00
parent 6d027e1fc2
commit 883cff405b
1 changed files with 104 additions and 62 deletions

View File

@ -84,12 +84,25 @@ inline static BOOL is_window_top_level( WND *win )
}
/***********************************************************************
* is_client_window_mapped
*
* Check if the X client window should be mapped
*/
inline static BOOL is_client_window_mapped( WND *win )
{
struct x11drv_win_data *data = win->pDriverData;
return !IsIconic( win->hwndSelf ) && !IsRectEmpty( &data->client_rect );
}
/***********************************************************************
* get_window_attributes
*
* Fill the window attributes structure for an X window
* Fill the window attributes structure for an X window.
* Returned cursor must be freed by caller.
*/
static int get_window_attributes( WND *win, XSetWindowAttributes *attr )
static int get_window_attributes( Display *display, WND *win, XSetWindowAttributes *attr )
{
BOOL is_top_level = is_window_top_level( win );
BOOL managed = is_top_level && is_window_managed( win );
@ -98,18 +111,35 @@ static int get_window_attributes( WND *win, XSetWindowAttributes *attr )
else win->dwExStyle &= ~WS_EX_MANAGED;
attr->override_redirect = !managed;
attr->bit_gravity = ForgetGravity;
attr->win_gravity = NorthWestGravity;
attr->colormap = X11DRV_PALETTE_PaletteXColormap;
attr->backing_store = NotUseful/*WhenMapped*/;
attr->save_under = ((win->clsStyle & CS_SAVEBITS) != 0);
attr->cursor = None;
attr->event_mask = (ExposureMask | KeyPressMask | KeyReleaseMask | PointerMotionMask |
ButtonPressMask | ButtonReleaseMask);
if (is_window_top_level( win )) attr->event_mask |= StructureNotifyMask | FocusChangeMask;
if (is_window_top_level( win ))
{
attr->event_mask |= StructureNotifyMask | FocusChangeMask;
attr->cursor = X11DRV_GetCursor( display, GlobalLock16(GetCursor()) );
}
return (CWOverrideRedirect | CWSaveUnder | CWEventMask | CWColormap | CWCursor);
}
return (CWBitGravity | CWWinGravity | CWBackingStore | CWOverrideRedirect |
CWSaveUnder | CWEventMask | CWColormap | CWCursor);
/***********************************************************************
* sync_window_style
*
* Change the X window attributes when the window style has changed.
*/
static void sync_window_style( Display *display, WND *win )
{
XSetWindowAttributes attr;
int mask;
wine_tsx11_lock();
mask = get_window_attributes( display, win, &attr );
XChangeWindowAttributes( display, get_whole_window(win), mask, &attr );
if (attr.cursor) XFreeCursor( display, attr.cursor );
wine_tsx11_unlock();
}
@ -196,11 +226,16 @@ static void set_icon_hints( Display *display, WND *wndPtr, XWMHints *hints )
if (data->hWMIconBitmap) DeleteObject( data->hWMIconBitmap );
if (data->hWMIconMask) DeleteObject( data->hWMIconMask);
data->hWMIconBitmap = 0;
data->hWMIconMask = 0;
if (!hIcon)
if (!(wndPtr->dwExStyle & WS_EX_MANAGED))
{
destroy_icon_window( display, data );
hints->flags &= ~(IconPixmapHint | IconMaskHint | IconWindowHint);
}
else if (!hIcon)
{
data->hWMIconBitmap = 0;
data->hWMIconMask = 0;
if (!data->icon_window) create_icon_window( display, wndPtr );
hints->icon_window = data->icon_window;
hints->flags = (hints->flags & ~(IconPixmapHint | IconMaskHint)) | IconWindowHint;
@ -277,7 +312,7 @@ static void set_size_hints( Display *display, WND *win )
*
* Set the window manager hints for a newly-created window
*/
inline static void set_wm_hints( Display *display, WND *win )
static void set_wm_hints( Display *display, WND *win )
{
struct x11drv_win_data *data = win->pDriverData;
Window group_leader;
@ -363,7 +398,7 @@ void X11DRV_set_iconic_state( WND *win )
if (!(win->dwExStyle & WS_EX_MANAGED))
{
if (iconic) TSXUnmapWindow( display, data->client_window );
else TSXMapWindow( display, data->client_window );
else if (is_client_window_mapped( win )) TSXMapWindow( display, data->client_window );
}
wine_tsx11_lock();
@ -533,12 +568,11 @@ int X11DRV_sync_client_window_position( Display *display, WND *win )
RECT client_rect = win->rectClient;
OffsetRect( &client_rect, -data->whole_rect.left, -data->whole_rect.top );
/* client rect cannot be empty */
if (client_rect.top >= client_rect.bottom) client_rect.bottom = client_rect.top + 1;
if (client_rect.left >= client_rect.right) client_rect.right = client_rect.left + 1;
if ((mask = get_window_changes( &changes, &data->client_rect, &client_rect )))
{
BOOL was_mapped = is_client_window_mapped( win );
TRACE( "setting win %lx pos %d,%d,%dx%d (was %d,%d,%dx%d) after %lx changes=%x\n",
data->client_window, client_rect.left, client_rect.top,
client_rect.right - client_rect.left, client_rect.bottom - client_rect.top,
@ -549,7 +583,11 @@ int X11DRV_sync_client_window_position( Display *display, WND *win )
data->client_rect = client_rect;
wine_tsx11_lock();
XSync( gdi_display, False ); /* flush graphics operations before moving the window */
if (was_mapped && !is_client_window_mapped( win ))
XUnmapWindow( display, data->client_window );
XConfigureWindow( display, data->client_window, mask, &changes );
if (!was_mapped && is_client_window_mapped( win ))
XMapWindow( display, data->client_window );
wine_tsx11_unlock();
}
return mask;
@ -609,8 +647,6 @@ static Window create_whole_window( Display *display, WND *win )
RECT rect;
BOOL is_top_level = is_window_top_level( win );
mask = get_window_attributes( win, &attr );
rect = win->rectWindow;
X11DRV_window_to_X_rect( win, &rect );
@ -621,7 +657,14 @@ static Window create_whole_window( Display *display, WND *win )
wine_tsx11_lock();
if (is_top_level) attr.cursor = X11DRV_GetCursor( display, GlobalLock16(GetCursor()) );
mask = get_window_attributes( display, win, &attr );
/* set the attributes that don't change over the lifetime of the window */
attr.bit_gravity = ForgetGravity;
attr.win_gravity = NorthWestGravity;
attr.backing_store = NotUseful/*WhenMapped*/;
mask |= CWBitGravity | CWWinGravity | CWBackingStore;
data->whole_rect = rect;
data->whole_window = XCreateWindow( display, parent, rect.left, rect.top, cx, cy,
0, screen_depth, InputOutput, visual,
@ -638,7 +681,7 @@ static Window create_whole_window( Display *display, WND *win )
XConfigureWindow( display, data->whole_window, CWStackMode, &changes );
}
if (is_top_level && !attr.override_redirect) set_wm_hints( display, win );
if (is_top_level) set_wm_hints( display, win );
done:
wine_tsx11_unlock();
@ -654,17 +697,9 @@ static Window create_whole_window( Display *display, WND *win )
static Window create_client_window( Display *display, WND *win )
{
struct x11drv_win_data *data = win->pDriverData;
RECT rect;
RECT rect = data->whole_rect;
XSetWindowAttributes attr;
rect = win->rectWindow;
SendMessageW( win->hwndSelf, WM_NCCALCSIZE, FALSE, (LPARAM)&rect );
if (rect.left > rect.right || rect.top > rect.bottom) rect = win->rectWindow;
if (rect.top >= rect.bottom) rect.bottom = rect.top + 1;
if (rect.left >= rect.right) rect.right = rect.left + 1;
win->rectClient = rect;
OffsetRect( &rect, -data->whole_rect.left, -data->whole_rect.top );
data->client_rect = rect;
@ -674,14 +709,16 @@ static Window create_client_window( Display *display, WND *win )
ForgetGravity : NorthWestGravity;
attr.backing_store = NotUseful/*WhenMapped*/;
data->client_window = TSXCreateWindow( display, data->whole_window,
rect.left, rect.top,
rect.right - rect.left,
rect.bottom - rect.top,
0, screen_depth,
InputOutput, visual,
CWEventMask | CWBitGravity | CWBackingStore, &attr );
if (data->client_window) TSXMapWindow( display, data->client_window );
wine_tsx11_lock();
data->client_window = XCreateWindow( display, data->whole_window, 0, 0,
max( rect.right - rect.left, 1 ),
max( rect.bottom - rect.top, 1 ),
0, screen_depth,
InputOutput, visual,
CWEventMask | CWBitGravity | CWBackingStore, &attr );
if (data->client_window && is_client_window_mapped( win ))
XMapWindow( display, data->client_window );
wine_tsx11_unlock();
return data->client_window;
}
@ -770,6 +807,7 @@ BOOL X11DRV_CreateWindow( HWND hwnd, CREATESTRUCTA *cs, BOOL unicode )
Display *display = thread_display();
WND *wndPtr;
struct x11drv_win_data *data;
RECT rect;
BOOL ret = FALSE;
if (!(data = HeapAlloc(GetProcessHeap(), 0, sizeof(*data)))) return FALSE;
@ -781,25 +819,10 @@ BOOL X11DRV_CreateWindow( HWND hwnd, CREATESTRUCTA *cs, BOOL unicode )
wndPtr = WIN_FindWndPtr( hwnd );
wndPtr->pDriverData = data;
WIN_ReleaseWndPtr( wndPtr );
if (unicode)
ret = SendMessageW( hwnd, WM_NCCREATE, 0, (LPARAM)cs );
else
ret = SendMessageA( hwnd, WM_NCCREATE, 0, (LPARAM)cs );
if (!ret)
{
X11DRV_DestroyWindow( hwnd );
return FALSE;
}
TRACE( "hwnd %x cs %d,%d %dx%d\n", hwnd, cs->x, cs->y, cs->cx, cs->cy );
if (!(wndPtr = WIN_FindWndPtr(hwnd))) return FALSE;
if (!wndPtr->parent)
{
SendMessageW( hwnd, WM_NCCREATE, 0, (LPARAM)cs );
create_desktop( display, wndPtr );
WIN_ReleaseWndPtr( wndPtr );
return TRUE;
@ -809,6 +832,32 @@ BOOL X11DRV_CreateWindow( HWND hwnd, CREATESTRUCTA *cs, BOOL unicode )
if (!create_client_window( display, wndPtr )) goto failed;
TSXSync( display, False );
WIN_ReleaseWndPtr( wndPtr );
/* send WM_NCCREATE */
TRACE( "hwnd %x 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)
{
X11DRV_DestroyWindow( hwnd );
return FALSE;
}
if (!(wndPtr = WIN_FindWndPtr(hwnd))) return FALSE;
sync_window_style( display, wndPtr );
/* send WM_NCCALCSIZE */
rect = wndPtr->rectWindow;
SendMessageW( hwnd, WM_NCCALCSIZE, FALSE, (LPARAM)&rect );
if (rect.left > rect.right || rect.top > rect.bottom) rect = wndPtr->rectWindow;
wndPtr->rectClient = rect;
X11DRV_sync_client_window_position( display, wndPtr );
X11DRV_register_window( display, hwnd, data );
TRACE( "win %x window %d,%d,%d,%d client %d,%d,%d,%d whole %d,%d,%d,%d X client %d,%d,%d,%d xwin %x/%x\n",
hwnd, wndPtr->rectWindow.left, wndPtr->rectWindow.top,
wndPtr->rectWindow.right, wndPtr->rectWindow.bottom,
@ -825,8 +874,6 @@ BOOL X11DRV_CreateWindow( HWND hwnd, CREATESTRUCTA *cs, BOOL unicode )
else
WIN_LinkWindow( hwnd, HWND_TOP );
if (wndPtr->text) X11DRV_SetWindowText( hwnd, wndPtr->text );
X11DRV_register_window( display, hwnd, data );
WIN_ReleaseWndPtr( wndPtr );
if (unicode)
@ -976,17 +1023,11 @@ HWND X11DRV_SetParent( HWND hwnd, HWND parent )
if (pWndParent != wndPtr->parent)
{
struct x11drv_win_data *data = wndPtr->pDriverData;
int mask;
XSetWindowAttributes attr;
WIN_UnlinkWindow(wndPtr->hwndSelf);
wndPtr->parent = pWndParent;
WIN_LinkWindow(wndPtr->hwndSelf, HWND_TOP);
mask = get_window_attributes( wndPtr, &attr );
if (is_window_top_level( wndPtr ) && !attr.override_redirect)
set_wm_hints( display, wndPtr );
if (parent != GetDesktopWindow()) /* a child window */
{
if (!(wndPtr->dwStyle & WS_CHILD) && wndPtr->wIDmenu)
@ -997,7 +1038,8 @@ HWND X11DRV_SetParent( HWND hwnd, HWND parent )
}
wine_tsx11_lock();
XChangeWindowAttributes( display, data->whole_window, mask, &attr );
sync_window_style( display, wndPtr );
if (is_window_top_level( wndPtr )) set_wm_hints( display, wndPtr );
XReparentWindow( display, data->whole_window, get_client_window(pWndParent),
data->whole_rect.left, data->whole_rect.top );
wine_tsx11_unlock();