Commit f777d70a authored by Alexandre Julliard's avatar Alexandre Julliard

Only create an X window for top-level windows, not for child windows.

Get rid of the X client window too, it's no longer needed.
parent 2dd40110
......@@ -638,7 +638,7 @@ HRESULT WINAPI IDirect3D8Impl_CreateDevice (LPDIRECT3D8 iface,
whichHWND = hFocusWindow;
}
object->win_handle = whichHWND;
object->win = (Window)GetPropA( whichHWND, "__wine_x11_client_window" );
object->win = (Window)GetPropA( whichHWND, "__wine_x11_whole_window" );
hDc = GetDC(whichHWND);
object->display = get_display(hDc);
......
......@@ -1375,7 +1375,7 @@ HRESULT WINAPI IWineD3DImpl_CreateDevice(IWineD3D *iface, UINT Adapter, D3DDEV
whichHWND = hFocusWindow;
}
object->win_handle = whichHWND;
object->win = (Window)GetPropA( whichHWND, "__wine_x11_client_window" );
object->win = (Window)GetPropA( whichHWND, "__wine_x11_whole_window" );
hDc = GetDC(whichHWND);
object->display = get_display(hDc);
ReleaseDC(whichHWND, hDc);
......
......@@ -68,24 +68,14 @@ static BYTE *pKeyStateTable;
*
* get the coordinates of a mouse event
*/
static void get_coords( HWND *hwnd, Window window, int x, int y, POINT *pt )
static inline void get_coords( HWND hwnd, Window window, int x, int y, POINT *pt )
{
struct x11drv_win_data *data = X11DRV_get_win_data( *hwnd );
struct x11drv_win_data *data = X11DRV_get_win_data( hwnd );
if (!data) return;
if (window == data->whole_window)
{
x -= data->client_rect.left;
y -= data->client_rect.top;
}
pt->x = x;
pt->y = y;
if (*hwnd != GetDesktopWindow())
{
ClientToScreen( *hwnd, pt );
*hwnd = GetAncestor( *hwnd, GA_ROOT );
}
pt->x = x + data->whole_rect.left;
pt->y = y + data->whole_rect.top;
}
......@@ -153,9 +143,6 @@ static void update_cursor( HWND hwnd, Window win )
{
struct x11drv_thread_data *data = x11drv_thread_data();
if (win == X11DRV_get_client_window( hwnd ))
win = X11DRV_get_whole_window( hwnd ); /* always set cursor on whole window */
if (data->cursor_window != win)
{
data->cursor_window = win;
......@@ -559,7 +546,7 @@ void X11DRV_ButtonPress( HWND hwnd, XButtonEvent *event )
if (!hwnd) return;
update_cursor( hwnd, event->window );
get_coords( &hwnd, event->window, event->x, event->y, &pt );
get_coords( hwnd, event->window, event->x, event->y, &pt );
switch (buttonNum)
{
......@@ -588,7 +575,7 @@ void X11DRV_ButtonRelease( HWND hwnd, XButtonEvent *event )
if (!hwnd) return;
update_cursor( hwnd, event->window );
get_coords( &hwnd, event->window, event->x, event->y, &pt );
get_coords( hwnd, event->window, event->x, event->y, &pt );
update_key_state( event->state );
send_mouse_event( hwnd, button_up_flags[buttonNum] | MOUSEEVENTF_ABSOLUTE,
pt.x, pt.y, 0, event->time );
......@@ -607,7 +594,7 @@ void X11DRV_MotionNotify( HWND hwnd, XMotionEvent *event )
if (!hwnd) return;
update_cursor( hwnd, event->window );
get_coords( &hwnd, event->window, event->x, event->y, &pt );
get_coords( hwnd, event->window, event->x, event->y, &pt );
update_key_state( event->state );
send_mouse_event( hwnd, MOUSEEVENTF_MOVE | MOUSEEVENTF_ABSOLUTE,
pt.x, pt.y, 0, event->time );
......@@ -628,7 +615,7 @@ void X11DRV_EnterNotify( HWND hwnd, XCrossingEvent *event )
/* simulate a mouse motion event */
update_cursor( hwnd, event->window );
get_coords( &hwnd, event->window, event->x, event->y, &pt );
get_coords( hwnd, event->window, event->x, event->y, &pt );
update_key_state( event->state );
send_mouse_event( hwnd, MOUSEEVENTF_MOVE | MOUSEEVENTF_ABSOLUTE,
pt.x, pt.y, 0, event->time );
......
......@@ -105,8 +105,8 @@ static const char * const atom_names[NB_XATOMS - FIRST_XATOM] =
};
static LPCSTR whole_window_atom;
static LPCSTR client_window_atom;
static LPCSTR icon_window_atom;
static LPCSTR client_offset_atom;
/***********************************************************************
* is_window_managed
......@@ -146,17 +146,6 @@ inline static BOOL is_window_managed( HWND hwnd )
/***********************************************************************
* is_client_window_mapped
*
* Check if the X client window should be mapped
*/
inline static BOOL is_client_window_mapped( struct x11drv_win_data *data )
{
return !(GetWindowLongW( data->hwnd, GWL_STYLE ) & WS_MINIMIZE) && !IsRectEmpty( &data->client_rect );
}
/***********************************************************************
* X11DRV_is_window_rect_mapped
*
* Check if the X whole window should be mapped based on its rectangle
......@@ -181,8 +170,7 @@ BOOL X11DRV_is_window_rect_mapped( const RECT *rect )
*/
static int get_window_attributes( struct x11drv_win_data *data, XSetWindowAttributes *attr )
{
BOOL is_top_level = is_window_top_level( data->hwnd );
BOOL managed = is_top_level && is_window_managed( data->hwnd );
BOOL managed = !using_wine_desktop && is_window_managed( data->hwnd );
DWORD ex_style = GetWindowLongW( data->hwnd, GWL_EXSTYLE );
if (managed) WIN_SetExStyle( data->hwnd, ex_style | WS_EX_MANAGED );
......@@ -193,11 +181,9 @@ static int get_window_attributes( struct x11drv_win_data *data, XSetWindowAttrib
attr->save_under = ((GetClassLongW( data->hwnd, GCL_STYLE ) & CS_SAVEBITS) != 0);
attr->cursor = x11drv_thread_data()->cursor;
attr->event_mask = (ExposureMask | PointerMotionMask |
ButtonPressMask | ButtonReleaseMask | EnterWindowMask);
if (is_top_level)
attr->event_mask |= (KeyPressMask | KeyReleaseMask | StructureNotifyMask |
FocusChangeMask | KeymapStateMask);
ButtonPressMask | ButtonReleaseMask | EnterWindowMask |
KeyPressMask | KeyReleaseMask | StructureNotifyMask |
FocusChangeMask | KeymapStateMask);
return (CWOverrideRedirect | CWSaveUnder | CWEventMask | CWColormap | CWCursor);
}
......@@ -285,7 +271,7 @@ static Window create_icon_window( Display *display, struct x11drv_win_data *data
/***********************************************************************
* destroy_icon_window
*/
inline static void destroy_icon_window( Display *display, struct x11drv_win_data *data )
static void destroy_icon_window( Display *display, struct x11drv_win_data *data )
{
if (!data->icon_window) return;
if (x11drv_thread_data()->cursor_window == data->icon_window)
......@@ -526,14 +512,12 @@ void X11DRV_set_iconic_state( HWND hwnd )
BOOL iconic = (style & WS_MINIMIZE) != 0;
if (!(data = X11DRV_get_win_data( hwnd ))) return;
if (!data->whole_window) return;
GetWindowRect( hwnd, &rect );
wine_tsx11_lock();
if (iconic) XUnmapWindow( display, data->client_window );
else if (!IsRectEmpty( &data->client_rect )) XMapWindow( display, data->client_window );
if (!(wm_hints = XGetWMHints( display, data->whole_window ))) wm_hints = XAllocWMHints();
wm_hints->flags |= StateHint | IconPositionHint;
wm_hints->initial_state = iconic ? IconicState : NormalState;
......@@ -603,69 +587,50 @@ void X11DRV_X_to_window_rect( HWND hwnd, RECT *rect )
/***********************************************************************
* X11DRV_sync_whole_window_position
* X11DRV_sync_window_position
*
* Synchronize the X whole window position with the Windows one
* Synchronize the X window position with the Windows one
*/
int X11DRV_sync_whole_window_position( Display *display, struct x11drv_win_data *data, int zorder )
void X11DRV_sync_window_position( Display *display, struct x11drv_win_data *data,
UINT swp_flags, const RECT *new_client_rect )
{
XWindowChanges changes;
int mask;
RECT whole_rect;
RECT old_whole_rect;
old_whole_rect = data->whole_rect;
data->whole_rect = data->window_rect;
X11DRV_window_to_X_rect( data->hwnd, &data->whole_rect );
data->client_rect = *new_client_rect;
OffsetRect( &data->client_rect, -data->whole_rect.left, -data->whole_rect.top );
SetPropA( data->hwnd, client_offset_atom,
(HANDLE)MAKELONG( data->client_rect.left, data->client_rect.top ));
whole_rect = data->window_rect;
X11DRV_window_to_X_rect( data->hwnd, &whole_rect );
mask = get_window_changes( &changes, &data->whole_rect, &whole_rect );
if (!data->whole_window) return;
if (swp_flags & SWP_WINE_NOHOSTMOVE) return;
if (zorder)
mask = get_window_changes( &changes, &old_whole_rect, &data->whole_rect );
if (!(swp_flags & SWP_NOZORDER))
{
if (is_window_top_level( data->hwnd ))
/* find window that this one must be after */
HWND prev = GetWindow( data->hwnd, GW_HWNDPREV );
while (prev && !(GetWindowLongW( prev, GWL_STYLE ) & WS_VISIBLE))
prev = GetWindow( prev, GW_HWNDPREV );
if (!prev) /* top child */
{
/* find window that this one must be after */
HWND prev = GetWindow( data->hwnd, GW_HWNDPREV );
while (prev && !(GetWindowLongW( prev, GWL_STYLE ) & WS_VISIBLE))
prev = GetWindow( prev, GW_HWNDPREV );
if (!prev) /* top child */
{
changes.stack_mode = Above;
mask |= CWStackMode;
}
else
{
/* should use stack_mode Below but most window managers don't get it right */
/* so move it above the next one in Z order */
HWND next = GetWindow( data->hwnd, GW_HWNDNEXT );
while (next && !(GetWindowLongW( next, GWL_STYLE ) & WS_VISIBLE))
next = GetWindow( next, GW_HWNDNEXT );
if (next)
{
changes.stack_mode = Above;
changes.sibling = X11DRV_get_whole_window(next);
mask |= CWStackMode | CWSibling;
}
}
changes.stack_mode = Above;
mask |= CWStackMode;
}
else
{
/* should use stack_mode Below but most window managers don't get it right */
/* so move it above the next one in Z order */
HWND next = GetWindow( data->hwnd, GW_HWNDNEXT );
if (GetAncestor( data->hwnd, GA_PARENT ) == GetDesktopWindow() &&
root_window != DefaultRootWindow(display))
{
/* in desktop mode we need the sibling to belong to the same process */
while (next)
{
if (X11DRV_get_win_data( next )) break;
next = GetWindow( next, GW_HWNDNEXT );
}
}
if (!next) /* bottom child */
{
changes.stack_mode = Below;
mask |= CWStackMode;
}
else
while (next && !(GetWindowLongW( next, GWL_STYLE ) & WS_VISIBLE))
next = GetWindow( next, GW_HWNDNEXT );
if (next)
{
changes.stack_mode = Above;
changes.sibling = X11DRV_get_whole_window(next);
......@@ -674,75 +639,22 @@ int X11DRV_sync_whole_window_position( Display *display, struct x11drv_win_data
}
}
data->whole_rect = whole_rect;
if (mask)
{
TRACE( "setting win %lx pos %ld,%ld,%ldx%ld after %lx changes=%x\n",
data->whole_window, whole_rect.left, whole_rect.top,
whole_rect.right - whole_rect.left, whole_rect.bottom - whole_rect.top,
changes.sibling, mask );
wine_tsx11_lock();
XSync( gdi_display, False ); /* flush graphics operations before moving the window */
wine_tsx11_unlock();
if (is_window_top_level( data->hwnd ))
{
DWORD style = GetWindowLongW( data->hwnd, GWL_STYLE );
wine_tsx11_lock();
if (mask & (CWWidth|CWHeight)) set_size_hints( display, data, style );
XReconfigureWMWindow( display, data->whole_window,
DefaultScreen(display), mask, &changes );
wine_tsx11_unlock();
}
else
{
wine_tsx11_lock();
XConfigureWindow( display, data->whole_window, mask, &changes );
wine_tsx11_unlock();
}
}
return mask;
}
/***********************************************************************
* X11DRV_sync_client_window_position
*
* Synchronize the X client window position with the Windows one
*/
int X11DRV_sync_client_window_position( Display *display, struct x11drv_win_data *data,
const RECT *new_client_rect )
{
XWindowChanges changes;
int mask;
RECT client_rect = *new_client_rect;
DWORD style = GetWindowLongW( data->hwnd, GWL_STYLE );
OffsetRect( &client_rect, -data->whole_rect.left, -data->whole_rect.top );
TRACE( "setting win %lx pos %ld,%ld,%ldx%ld after %lx changes=%x\n",
data->whole_window, data->whole_rect.left, data->whole_rect.top,
data->whole_rect.right - data->whole_rect.left,
data->whole_rect.bottom - data->whole_rect.top, changes.sibling, mask );
if ((mask = get_window_changes( &changes, &data->client_rect, &client_rect )))
{
BOOL is_mapped;
TRACE( "setting win %lx pos %ld,%ld,%ldx%ld (was %ld,%ld,%ldx%ld) 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,
data->client_rect.left, data->client_rect.top,
data->client_rect.right - data->client_rect.left,
data->client_rect.bottom - data->client_rect.top,
changes.sibling, mask );
data->client_rect = client_rect;
is_mapped = is_client_window_mapped( data );
wine_tsx11_lock();
XSync( gdi_display, False ); /* flush graphics operations before moving the window */
if (!is_mapped) XUnmapWindow( display, data->client_window );
XConfigureWindow( display, data->client_window, mask, &changes );
if (is_mapped) XMapWindow( display, data->client_window );
if (mask & (CWWidth|CWHeight)) set_size_hints( display, data, style );
XReconfigureWMWindow( display, data->whole_window,
DefaultScreen(display), mask, &changes );
wine_tsx11_unlock();
}
return mask;
}
......@@ -760,14 +672,13 @@ static void create_desktop( Display *display, struct x11drv_win_data *data )
wine_tsx11_unlock();
whole_window_atom = MAKEINTATOMA( GlobalAddAtomA( "__wine_x11_whole_window" ));
client_window_atom = MAKEINTATOMA( GlobalAddAtomA( "__wine_x11_client_window" ));
icon_window_atom = MAKEINTATOMA( GlobalAddAtomA( "__wine_x11_icon_window" ));
client_offset_atom = MAKEINTATOMA( GlobalAddAtomA( "__wine_x11_client_area_offset" ));
data->whole_window = data->client_window = root_window;
data->whole_window = root_window;
data->whole_rect = data->client_rect = data->window_rect;
SetPropA( data->hwnd, whole_window_atom, (HANDLE)root_window );
SetPropA( data->hwnd, client_window_atom, (HANDLE)root_window );
SetPropA( data->hwnd, "__wine_x11_visual_id", (HANDLE)visualid );
X11DRV_InitClipboard();
......@@ -785,9 +696,8 @@ static Window create_whole_window( Display *display, struct x11drv_win_data *dat
{
int cx, cy, mask;
XSetWindowAttributes attr;
Window parent;
XIM xim;
RECT rect;
BOOL is_top_level = is_window_top_level( data->hwnd );
rect = data->window_rect;
X11DRV_window_to_X_rect( data->hwnd, &rect );
......@@ -795,8 +705,6 @@ static Window create_whole_window( Display *display, struct x11drv_win_data *dat
if (!(cx = rect.right - rect.left)) cx = 1;
if (!(cy = rect.bottom - rect.top)) cy = 1;
parent = X11DRV_get_client_window( GetAncestor( data->hwnd, GA_PARENT ) );
mask = get_window_attributes( data, &attr );
/* set the attributes that don't change over the lifetime of the window */
......@@ -808,7 +716,7 @@ static Window create_whole_window( Display *display, struct x11drv_win_data *dat
wine_tsx11_lock();
data->whole_rect = rect;
data->whole_window = XCreateWindow( display, parent, rect.left, rect.top, cx, cy,
data->whole_window = XCreateWindow( display, root_window, rect.left, rect.top, cx, cy,
0, screen_depth, InputOutput, visual,
mask, &attr );
......@@ -826,52 +734,45 @@ static Window create_whole_window( Display *display, struct x11drv_win_data *dat
changes.stack_mode = Below;
XConfigureWindow( display, data->whole_window, CWStackMode, &changes );
}
XSync( display, False ); /* FIXME: should not be needed */
wine_tsx11_unlock();
if (is_top_level)
{
XIM xim = x11drv_thread_data()->xim;
if (xim) data->xic = X11DRV_CreateIC( xim, display, data->whole_window );
X11DRV_set_wm_hints( display, data );
}
xim = x11drv_thread_data()->xim;
if (xim) data->xic = X11DRV_CreateIC( xim, display, data->whole_window );
X11DRV_set_wm_hints( display, data );
SetPropA( data->hwnd, whole_window_atom, (HANDLE)data->whole_window );
return data->whole_window;
}
/**********************************************************************
* create_client_window
* destroy_whole_window
*
* Create the client window for a given window
* Destroy the whole X window for a given window.
*/
static Window create_client_window( Display *display, struct x11drv_win_data *data )
static void destroy_whole_window( Display *display, struct x11drv_win_data *data )
{
RECT rect = data->whole_rect;
XSetWindowAttributes attr;
BOOL is_mapped;
struct x11drv_thread_data *thread_data = x11drv_thread_data();
OffsetRect( &rect, -data->whole_rect.left, -data->whole_rect.top );
data->client_rect = rect;
is_mapped = is_client_window_mapped( data );
attr.event_mask = (ExposureMask | PointerMotionMask |
ButtonPressMask | ButtonReleaseMask | EnterWindowMask);
attr.bit_gravity = (GetClassLongW( data->hwnd, GCL_STYLE ) & (CS_VREDRAW | CS_HREDRAW)) ?
ForgetGravity : NorthWestGravity;
attr.backing_store = NotUseful/*WhenMapped*/;
if (!data->whole_window) return;
TRACE( "win %p xwin %lx\n", data->hwnd, data->whole_window );
if (thread_data->cursor_window == data->whole_window) thread_data->cursor_window = None;
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 );
XSaveContext( display, data->client_window, winContext, (char *)data->hwnd );
if (data->client_window && is_mapped) XMapWindow( display, data->client_window );
XSync( gdi_display, False ); /* flush any reference to this drawable in GDI queue */
XDeleteContext( display, data->whole_window, winContext );
XDestroyWindow( display, data->whole_window ); /* this destroys client too */
data->whole_window = 0;
if (data->xic)
{
XUnsetICFocus( data->xic );
XDestroyIC( data->xic );
}
wine_tsx11_unlock();
return data->client_window;
RemovePropA( data->hwnd, whole_window_atom );
}
......@@ -942,25 +843,10 @@ BOOL X11DRV_DestroyWindow( HWND hwnd )
if (!(data = X11DRV_get_win_data( hwnd ))) goto done;
if (data->whole_window)
{
TRACE( "win %p xwin %lx/%lx\n", hwnd, data->whole_window, data->client_window );
if (thread_data->cursor_window == data->whole_window) thread_data->cursor_window = None;
if (thread_data->last_focus == hwnd) thread_data->last_focus = 0;
wine_tsx11_lock();
XSync( gdi_display, False ); /* flush any reference to this drawable in GDI queue */
XDeleteContext( display, data->whole_window, winContext );
XDeleteContext( display, data->client_window, winContext );
XDestroyWindow( display, data->whole_window ); /* this destroys client too */
if (data->xic)
{
XUnsetICFocus( data->xic );
XDestroyIC( data->xic );
}
wine_tsx11_unlock();
destroy_icon_window( display, data );
}
destroy_whole_window( display, data );
destroy_icon_window( display, data );
if (thread_data->last_focus == hwnd) thread_data->last_focus = 0;
if (data->hWMIconBitmap) DeleteObject( data->hWMIconBitmap );
if (data->hWMIconMask) DeleteObject( data->hWMIconMask);
wine_tsx11_lock();
......@@ -1012,7 +898,6 @@ BOOL X11DRV_CreateWindow( HWND hwnd, CREATESTRUCTA *cs, BOOL unicode )
if (!(data = HeapAlloc(GetProcessHeap(), 0, sizeof(*data)))) return FALSE;
data->hwnd = hwnd;
data->whole_window = 0;
data->client_window = 0;
data->icon_window = 0;
data->xic = 0;
data->hWMIconBitmap = 0;
......@@ -1035,14 +920,11 @@ BOOL X11DRV_CreateWindow( HWND hwnd, CREATESTRUCTA *cs, BOOL unicode )
return TRUE;
}
if (!create_whole_window( display, data, cs->style )) goto failed;
if (!create_client_window( display, data )) goto failed;
wine_tsx11_lock();
XSync( display, False );
wine_tsx11_unlock();
SetPropA( hwnd, whole_window_atom, (HANDLE)data->whole_window );
SetPropA( hwnd, client_window_atom, (HANDLE)data->client_window );
/* create an X window if it's a top level window */
if (parent == GetDesktopWindow())
{
if (!create_whole_window( display, data, cs->style )) goto failed;
}
/* Call the WH_CBT hook */
cbtc.lpcs = cs;
......@@ -1082,7 +964,7 @@ BOOL X11DRV_CreateWindow( HWND hwnd, CREATESTRUCTA *cs, BOOL unicode )
/* make sure the window is still valid */
if (!(data = X11DRV_get_win_data( hwnd ))) return FALSE;
X11DRV_sync_window_style( display, data );
if (data->whole_window) X11DRV_sync_window_style( display, data );
/* send WM_NCCALCSIZE */
rect = data->window_rect;
......@@ -1100,7 +982,7 @@ BOOL X11DRV_CreateWindow( HWND hwnd, CREATESTRUCTA *cs, BOOL unicode )
X11DRV_set_window_pos( hwnd, insert_after, &wndPtr->rectWindow, &rect, 0, 0 );
TRACE( "win %p window %ld,%ld,%ld,%ld client %ld,%ld,%ld,%ld whole %ld,%ld,%ld,%ld X client %ld,%ld,%ld,%ld xwin %x/%x\n",
TRACE( "win %p window %ld,%ld,%ld,%ld client %ld,%ld,%ld,%ld whole %ld,%ld,%ld,%ld X client %ld,%ld,%ld,%ld xwin %x\n",
hwnd, wndPtr->rectWindow.left, wndPtr->rectWindow.top,
wndPtr->rectWindow.right, wndPtr->rectWindow.bottom,
wndPtr->rectClient.left, wndPtr->rectClient.top,
......@@ -1109,7 +991,7 @@ BOOL X11DRV_CreateWindow( HWND hwnd, CREATESTRUCTA *cs, BOOL unicode )
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, (unsigned int)data->client_window );
(unsigned int)data->whole_window );
WIN_ReleasePtr( wndPtr );
......@@ -1181,16 +1063,27 @@ struct x11drv_win_data *X11DRV_get_win_data( HWND hwnd )
/***********************************************************************
* X11DRV_get_client_window
* X11DRV_get_client_area_offset
*
* Return the X window associated with the client area of a window
* Return the offset of the client area relative to the x11 window.
*/
Window X11DRV_get_client_window( HWND hwnd )
POINT X11DRV_get_client_area_offset( HWND hwnd )
{
POINT pt;
struct x11drv_win_data *data = X11DRV_get_win_data( hwnd );
if (!data) return (Window)GetPropA( hwnd, client_window_atom );
return data->client_window;
if (data)
{
pt.x = data->client_rect.left;
pt.y = data->client_rect.top;
}
else
{
ULONG_PTR offset = (ULONG_PTR)GetPropA( hwnd, client_offset_atom );
pt.x = (SHORT)LOWORD(offset);
pt.y = (SHORT)HIWORD(offset);
}
return pt;
}
......@@ -1240,7 +1133,6 @@ HWND X11DRV_SetParent( HWND hwnd, HWND parent )
if (parent != old_parent)
{
struct x11drv_win_data *data;
Window new_parent = X11DRV_get_client_window( parent );
if (!(data = X11DRV_get_win_data( hwnd ))) return 0;
......@@ -1253,14 +1145,18 @@ HWND X11DRV_SetParent( HWND hwnd, HWND parent )
HMENU menu = (HMENU)SetWindowLongPtrW( hwnd, GWLP_ID, 0 );
if (menu) DestroyMenu( menu );
}
if (old_parent == GetDesktopWindow())
{
/* destroy the old X windows */
destroy_whole_window( display, data );
destroy_icon_window( display, data );
}
}
else /* new top level window */
{
/* FIXME: we ignore errors since we can't really recover anyway */
create_whole_window( display, data, GetWindowLongW( hwnd, GWL_STYLE ) );
}
if (is_window_top_level( data->hwnd )) X11DRV_set_wm_hints( display, data );
X11DRV_sync_window_style( display, data );
wine_tsx11_lock();
XReparentWindow( display, data->whole_window, new_parent,
data->whole_rect.left, data->whole_rect.top );
wine_tsx11_unlock();
}
/* SetParent additionally needs to make hwnd the topmost window
......@@ -1343,6 +1239,7 @@ void X11DRV_SetWindowIcon( HWND hwnd, UINT type, HICON icon )
if (type != ICON_BIG) return; /* nothing to do here */
if (!(data = X11DRV_get_win_data( hwnd ))) return;
if (!data->whole_window) return;
ex_style = GetWindowLongW( hwnd, GWL_EXSTYLE );
if (ex_style & WS_EX_MANAGED)
......
......@@ -131,83 +131,20 @@ static HRGN get_server_visible_region( HWND hwnd, HWND top, UINT flags )
*/
static HWND get_top_clipping_window( HWND hwnd )
{
HWND ret = 0;
if (!using_wine_desktop) ret = GetAncestor( hwnd, GA_ROOT );
HWND ret = GetAncestor( hwnd, GA_ROOT );
if (!ret) ret = GetDesktopWindow();
return ret;
}
/***********************************************************************
* expose_window
*
* Expose a region of a given window.
*/
static void expose_window( HWND hwnd, RECT *rect, HRGN rgn, int flags )
{
POINT offset;
HWND top = 0;
HWND *list;
int i;
/* find the top most parent that doesn't clip children or siblings and
* invalidate the area on its parent, including all children */
if ((list = WIN_ListParents( hwnd )))
{
HWND current = hwnd;
LONG style = GetWindowLongW( hwnd, GWL_STYLE );
for (i = 0; list[i] && list[i] != GetDesktopWindow(); i++)
{
if (!(style & WS_CLIPSIBLINGS)) top = current;
style = GetWindowLongW( list[i], GWL_STYLE );
if (!(style & WS_CLIPCHILDREN)) top = current;
current = list[i];
}
if (top)
{
/* find the parent of the top window, reusing the parent list */
if (top == hwnd) i = 0;
else
{
for (i = 0; list[i]; i++) if (list[i] == top) break;
if (list[i] && list[i+1]) i++;
}
if (list[i] != GetDesktopWindow()) top = list[i];
flags &= ~RDW_FRAME; /* parent will invalidate children frame anyway */
flags |= RDW_ALLCHILDREN;
}
HeapFree( GetProcessHeap(), 0, list );
}
if (!top) top = hwnd;
/* make coords relative to top */
offset.x = offset.y = 0;
MapWindowPoints( hwnd, top, &offset, 1 );
if (rect)
{
OffsetRect( rect, offset.x, offset.y );
RedrawWindow( top, rect, 0, flags );
}
else
{
OffsetRgn( rgn, offset.x, offset.y );
RedrawWindow( top, NULL, rgn, flags );
}
}
/***********************************************************************
* X11DRV_Expose
*/
void X11DRV_Expose( HWND hwnd, XExposeEvent *event )
{
RECT rect;
struct x11drv_win_data *data;
int flags = RDW_INVALIDATE | RDW_ERASE;
int flags = RDW_INVALIDATE | RDW_ERASE | RDW_ALLCHILDREN;
TRACE( "win %p (%lx) %d,%d %dx%d\n",
hwnd, event->window, event->x, event->y, event->width, event->height );
......@@ -219,14 +156,15 @@ void X11DRV_Expose( HWND hwnd, XExposeEvent *event )
rect.right = rect.left + event->width;
rect.bottom = rect.top + event->height;
if (event->window != data->client_window) /* whole window or icon window */
{
flags |= RDW_FRAME;
/* make position relative to client area instead of window */
OffsetRect( &rect, -data->client_rect.left, -data->client_rect.top );
}
if (rect.left < data->client_rect.left ||
rect.top < data->client_rect.top ||
rect.right > data->client_rect.right ||
rect.bottom > data->client_rect.bottom) flags |= RDW_FRAME;
expose_window( hwnd, &rect, 0, flags );
/* make position relative to client area instead of window */
OffsetRect( &rect, -data->client_rect.left, -data->client_rect.top );
RedrawWindow( hwnd, &rect, 0, flags );
}
......@@ -239,7 +177,6 @@ void X11DRV_Expose( HWND hwnd, XExposeEvent *event )
BOOL X11DRV_GetDC( HWND hwnd, HDC hdc, HRGN hrgn, DWORD flags )
{
HWND top = get_top_clipping_window( hwnd );
WND *win = WIN_GetPtr( hwnd );
struct x11drv_escape_set_drawable escape;
escape.mode = IncludeInferiors;
......@@ -248,46 +185,39 @@ BOOL X11DRV_GetDC( HWND hwnd, HDC hdc, HRGN hrgn, DWORD flags )
if (top != hwnd)
{
/* find the top most parent that doesn't clip siblings */
HWND clipping_parent = 0;
HWND *list = WIN_ListParents( hwnd );
if (list)
POINT client_offset;
if (flags & DCX_WINDOW)
{
int i;
for (i = 0; list[i] != top; i++)
{
LONG style = GetWindowLongW( list[i], GWL_STYLE );
if (!(style & WS_CLIPSIBLINGS)) clipping_parent = list[i];
}
HeapFree( GetProcessHeap(), 0, list );
RECT rect;
GetWindowRect( hwnd, &rect );
escape.org.x = rect.left;
escape.org.y = rect.top;
MapWindowPoints( 0, top, &escape.org, 1 );
escape.drawable_org.x = rect.left - escape.org.x;
escape.drawable_org.y = rect.top - escape.org.y;
}
if (clipping_parent)
clipping_parent = GetAncestor( clipping_parent, GA_PARENT );
else if (!(flags & DCX_CLIPSIBLINGS) || (flags & DCX_WINDOW))
clipping_parent = GetAncestor( hwnd, GA_PARENT );
else
clipping_parent = hwnd;
escape.org.x = escape.org.y = 0;
escape.drawable_org.x = escape.drawable_org.y = 0;
if (flags & DCX_WINDOW)
{
escape.org.x = win->rectWindow.left - win->rectClient.left;
escape.org.y = win->rectWindow.top - win->rectClient.top;
escape.org.x = escape.org.y = 0;
escape.drawable_org.x = escape.drawable_org.y = 0;
MapWindowPoints( hwnd, top, &escape.org, 1 );
MapWindowPoints( top, 0, &escape.drawable_org, 1 );
}
MapWindowPoints( hwnd, clipping_parent, &escape.org, 1 );
MapWindowPoints( clipping_parent, 0, &escape.drawable_org, 1 );
escape.drawable = X11DRV_get_client_window( clipping_parent );
/* now make origins relative to the X window and not the client area */
client_offset = X11DRV_get_client_area_offset( top );
escape.org.x += client_offset.x;
escape.org.y += client_offset.y;
escape.drawable_org.x -= client_offset.x;
escape.drawable_org.y -= client_offset.y;
escape.drawable = X11DRV_get_whole_window( top );
}
else
{
struct x11drv_win_data *data;
if (!(data = X11DRV_get_win_data( hwnd )))
{
WIN_ReleasePtr( win );
return FALSE;
}
if (!(data = X11DRV_get_win_data( hwnd ))) return FALSE;
if (IsIconic( hwnd ))
{
......@@ -296,21 +226,21 @@ BOOL X11DRV_GetDC( HWND hwnd, HDC hdc, HRGN hrgn, DWORD flags )
escape.org.y = 0;
escape.drawable_org = escape.org;
}
else if (flags & DCX_WINDOW)
else
{
escape.drawable = data->whole_window;
escape.drawable_org.x = data->whole_rect.left;
escape.drawable_org.y = data->whole_rect.top;
escape.org.x = win->rectWindow.left - data->whole_rect.left;
escape.org.y = win->rectWindow.top - data->whole_rect.top;
}
else
{
escape.drawable = data->client_window;
escape.drawable_org.x = win->rectClient.left;
escape.drawable_org.y = win->rectClient.top;
escape.org.x = 0;
escape.org.y = 0;
if (flags & DCX_WINDOW)
{
escape.org.x = data->window_rect.left - data->whole_rect.left;
escape.org.y = data->window_rect.top - data->whole_rect.top;
}
else
{
escape.org.x = data->client_rect.left;
escape.org.y = data->client_rect.top;
}
}
}
......@@ -329,8 +259,6 @@ BOOL X11DRV_GetDC( HWND hwnd, HDC hdc, HRGN hrgn, DWORD flags )
SelectVisRgn16( HDC_16(hdc), HRGN_16(visRgn) );
DeleteObject( visRgn );
}
WIN_ReleasePtr( win );
return TRUE;
}
......@@ -636,34 +564,25 @@ void X11DRV_SetWindowStyle( HWND hwnd, DWORD old_style )
if (changed & WS_VISIBLE)
{
if (X11DRV_is_window_rect_mapped( &data->window_rect ))
if (data->whole_window && X11DRV_is_window_rect_mapped( &data->window_rect ))
{
if (new_style & WS_VISIBLE)
{
TRACE( "mapping win %p\n", hwnd );
if (is_window_top_level( hwnd ))
{
X11DRV_sync_window_style( display, data );
X11DRV_set_wm_hints( display, data );
}
X11DRV_sync_window_style( display, data );
X11DRV_set_wm_hints( display, data );
wine_tsx11_lock();
XMapWindow( display, data->whole_window );
wine_tsx11_unlock();
}
else if (!is_window_top_level( hwnd )) /* don't unmap managed windows */
{
TRACE( "unmapping win %p\n", hwnd );
wine_tsx11_lock();
XUnmapWindow( display, data->whole_window );
wine_tsx11_unlock();
}
/* we don't unmap windows, that causes trouble with the window manager */
}
DCE_InvalidateDCE( hwnd, &data->window_rect );
}
if (changed & WS_DISABLED)
{
if (GetWindowLongW( hwnd, GWL_EXSTYLE ) & WS_EX_MANAGED)
if (data->whole_window && (GetWindowLongW( hwnd, GWL_EXSTYLE ) & WS_EX_MANAGED))
{
XWMHints *wm_hints;
wine_tsx11_lock();
......@@ -748,14 +667,7 @@ BOOL X11DRV_set_window_pos( HWND hwnd, HWND insert_after, const RECT *rectWindow
/* FIXME: copy the valid bits */
if (swp_flags & SWP_WINE_NOHOSTMOVE)
{
data->whole_rect = *rectWindow;
X11DRV_window_to_X_rect( hwnd, &data->whole_rect );
if (data->client_window != data->whole_window)
X11DRV_sync_client_window_position( display, data, rectClient );
}
else if (data->whole_window) /* don't do anything if X window not created yet */
if (data->whole_window)
{
if ((old_style & WS_VISIBLE) && !(new_style & WS_VISIBLE))
{
......@@ -773,21 +685,20 @@ BOOL X11DRV_set_window_pos( HWND hwnd, HWND insert_after, const RECT *rectWindow
XUnmapWindow( display, data->whole_window );
wine_tsx11_unlock();
}
}
X11DRV_sync_whole_window_position( display, data, !(swp_flags & SWP_NOZORDER) );
X11DRV_sync_client_window_position( display, data, rectClient );
X11DRV_sync_window_position( display, data, swp_flags, rectClient );
if (data->whole_window)
{
if (!(old_style & WS_VISIBLE) && (new_style & WS_VISIBLE))
{
/* window got shown, map it */
if (X11DRV_is_window_rect_mapped( rectWindow ))
{
TRACE( "mapping win %p\n", hwnd );
if (is_window_top_level( hwnd ))
{
X11DRV_sync_window_style( display, data );
X11DRV_set_wm_hints( display, data );
}
X11DRV_sync_window_style( display, data );
X11DRV_set_wm_hints( display, data );
wine_tsx11_lock();
XMapWindow( display, data->whole_window );
wine_tsx11_unlock();
......@@ -1226,7 +1137,7 @@ void X11DRV_MapNotify( HWND hwnd, XMapEvent *event )
rect.bottom = y + height;
X11DRV_X_to_window_rect( hwnd, &rect );
DCE_InvalidateDCE( hwnd, &win->rectWindow );
DCE_InvalidateDCE( hwnd, &data->window_rect );
if (win->flags & WIN_RESTORE_MAX) style |= WS_MAXIMIZE;
WIN_SetStyle( hwnd, style, WS_MINIMIZE );
......@@ -1878,8 +1789,8 @@ void X11DRV_SysCommandSizeMove( HWND hwnd, WPARAM wParam )
gdi_display = display;
wine_tsx11_unlock();
}
whole_win = X11DRV_get_whole_window(hwnd);
parent_win = parent ? X11DRV_get_client_window(parent) : root_window;
whole_win = X11DRV_get_whole_window( GetAncestor(hwnd,GA_ROOT) );
parent_win = parent ? X11DRV_get_whole_window( GetAncestor(parent,GA_ROOT) ) : root_window;
wine_tsx11_lock();
XGrabPointer( display, whole_win, False,
......
......@@ -531,7 +531,6 @@ struct x11drv_win_data
{
HWND hwnd; /* hwnd that this private data belongs to */
Window whole_window; /* X window for the complete window */
Window client_window; /* X window for the client area */
Window icon_window; /* X window for the icon */
RECT window_rect; /* USER window rectangle relative to parent */
RECT whole_rect; /* X window rectangle for the whole window relative to parent */
......@@ -542,16 +541,11 @@ struct x11drv_win_data
};
extern struct x11drv_win_data *X11DRV_get_win_data( HWND hwnd );
extern Window X11DRV_get_client_window( HWND hwnd );
extern POINT X11DRV_get_client_area_offset( HWND hwnd );
extern Window X11DRV_get_whole_window( HWND hwnd );
extern BOOL X11DRV_is_window_rect_mapped( const RECT *rect );
extern XIC X11DRV_get_ic( HWND hwnd );
inline static BOOL is_window_top_level( HWND hwnd )
{
return (root_window == DefaultRootWindow(gdi_display) &&
GetAncestor( hwnd, GA_PARENT ) == GetDesktopWindow());
}
/* X context to associate a hwnd to an X window */
extern XContext winContext;
......@@ -569,10 +563,8 @@ extern void X11DRV_X_to_window_rect( HWND hwnd, RECT *rect );
extern void X11DRV_create_desktop_thread(void);
extern Window X11DRV_create_desktop( XVisualInfo *desktop_vi, const char *geometry );
extern void X11DRV_sync_window_style( Display *display, struct x11drv_win_data *data );
extern int X11DRV_sync_whole_window_position( Display *display, struct x11drv_win_data *data,
int zorder );
extern int X11DRV_sync_client_window_position( Display *display, struct x11drv_win_data *data,
const RECT *new_client_rect );
extern void X11DRV_sync_window_position( Display *display, struct x11drv_win_data *data,
UINT swp_flags, const RECT *new_client_rect );
extern BOOL X11DRV_set_window_pos( HWND hwnd, HWND insert_after, const RECT *rectWindow,
const RECT *rectClient, UINT swp_flags, UINT wvr_flags );
extern void X11DRV_set_wm_hints( Display *display, struct x11drv_win_data *data );
......
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