From 855308fd95257ff811c40390c790b4100b5d2214 Mon Sep 17 00:00:00 2001 From: Alexandre Julliard Date: Wed, 23 Apr 2008 15:32:58 +0200 Subject: [PATCH] winex11: Merged the contents of winpos.c into window.c. --- dlls/winex11.drv/Makefile.in | 1 - dlls/winex11.drv/event.c | 2 +- dlls/winex11.drv/window.c | 449 +++++++++++++++++++++++++++++++++++++++-- dlls/winex11.drv/winpos.c | 466 ------------------------------------------- dlls/winex11.drv/x11drv.h | 12 +- 5 files changed, 438 insertions(+), 492 deletions(-) delete mode 100644 dlls/winex11.drv/winpos.c diff --git a/dlls/winex11.drv/Makefile.in b/dlls/winex11.drv/Makefile.in index 4d7df18089f..20bdd56e2e0 100644 --- a/dlls/winex11.drv/Makefile.in +++ b/dlls/winex11.drv/Makefile.in @@ -34,7 +34,6 @@ C_SRCS = \ systray.c \ text.c \ window.c \ - winpos.c \ wintab.c \ x11ddraw.c \ x11drv_main.c \ diff --git a/dlls/winex11.drv/event.c b/dlls/winex11.drv/event.c index 2cb8cc8fdb3..36aa088cc30 100644 --- a/dlls/winex11.drv/event.c +++ b/dlls/winex11.drv/event.c @@ -797,7 +797,7 @@ void X11DRV_ConfigureNotify( HWND hwnd, XEvent *xev ) /*********************************************************************** * get_window_wm_state */ -int get_window_wm_state( Display *display, struct x11drv_win_data *data ) +static int get_window_wm_state( Display *display, struct x11drv_win_data *data ) { struct { diff --git a/dlls/winex11.drv/window.c b/dlls/winex11.drv/window.c index 996bb8ed1dc..95b43a7ea56 100644 --- a/dlls/winex11.drv/window.c +++ b/dlls/winex11.drv/window.c @@ -62,6 +62,12 @@ WINE_DEFAULT_DEBUG_CHANNEL(x11drv); #define _NET_WM_MOVERESIZE_SIZE_KEYBOARD 9 #define _NET_WM_MOVERESIZE_MOVE_KEYBOARD 10 +#define _NET_WM_STATE_REMOVE 0 +#define _NET_WM_STATE_ADD 1 +#define _NET_WM_STATE_TOGGLE 2 + +#define SWP_AGG_NOPOSCHANGE (SWP_NOSIZE | SWP_NOMOVE | SWP_NOCLIENTSIZE | SWP_NOCLIENTMOVE | SWP_NOZORDER) + /* X context to associate a hwnd to an X window */ XContext winContext = 0; @@ -76,14 +82,12 @@ static const char gl_drawable_prop[] = "__wine_x11_gl_drawable"; static const char pixmap_prop[] = "__wine_x11_pixmap"; static const char managed_prop[] = "__wine_x11_managed"; -extern int usexcomposite; - /*********************************************************************** * is_window_managed * * Check if a given window should be managed */ -BOOL is_window_managed( HWND hwnd, UINT swp_flags, const RECT *window_rect ) +static BOOL is_window_managed( HWND hwnd, UINT swp_flags, const RECT *window_rect ) { DWORD style, ex_style; @@ -123,7 +127,7 @@ BOOL is_window_managed( HWND hwnd, UINT swp_flags, const RECT *window_rect ) * * Check if the X whole window should be mapped based on its rectangle */ -BOOL X11DRV_is_window_rect_mapped( const RECT *rect ) +static BOOL is_window_rect_mapped( const RECT *rect ) { /* don't map if rect is off-screen */ if (rect->left >= virtual_screen_rect.right || @@ -291,11 +295,11 @@ static Window create_client_window( Display *display, struct x11drv_win_data *da /*********************************************************************** - * X11DRV_sync_window_style + * sync_window_style * * Change the X window attributes when the window style has changed. */ -void X11DRV_sync_window_style( Display *display, struct x11drv_win_data *data ) +static void sync_window_style( Display *display, struct x11drv_win_data *data ) { if (data->whole_window != root_window) { @@ -836,11 +840,11 @@ static void set_initial_wm_hints( Display *display, struct x11drv_win_data *data /*********************************************************************** - * X11DRV_set_wm_hints + * set_wm_hints * * Set the window manager hints for a newly-created window */ -void X11DRV_set_wm_hints( Display *display, struct x11drv_win_data *data ) +static void set_wm_hints( Display *display, struct x11drv_win_data *data ) { Window group_leader; Atom window_type; @@ -919,6 +923,181 @@ void X11DRV_set_wm_hints( Display *display, struct x11drv_win_data *data ) /*********************************************************************** + * update_net_wm_states + */ +void update_net_wm_states( Display *display, struct x11drv_win_data *data ) +{ + static const unsigned int state_atoms[NB_NET_WM_STATES] = + { + XATOM__NET_WM_STATE_FULLSCREEN, + XATOM__NET_WM_STATE_ABOVE, + XATOM__NET_WM_STATE_MAXIMIZED_VERT, + XATOM__NET_WM_STATE_SKIP_PAGER, + XATOM__NET_WM_STATE_SKIP_TASKBAR + }; + + DWORD i, style, ex_style, new_state = 0; + + if (!data->managed) return; + if (data->whole_window == root_window) return; + + style = GetWindowLongW( data->hwnd, GWL_STYLE ); + if (data->whole_rect.left <= 0 && data->whole_rect.right >= screen_width && + data->whole_rect.top <= 0 && data->whole_rect.bottom >= screen_height) + { + if ((style & WS_MAXIMIZE) && (style & WS_CAPTION) == WS_CAPTION) + new_state |= (1 << NET_WM_STATE_MAXIMIZED); + else if (!(style & WS_MINIMIZE)) + new_state |= (1 << NET_WM_STATE_FULLSCREEN); + } + else if (style & WS_MAXIMIZE) + new_state |= (1 << NET_WM_STATE_MAXIMIZED); + + ex_style = GetWindowLongW( data->hwnd, GWL_EXSTYLE ); + if (ex_style & WS_EX_TOPMOST) + new_state |= (1 << NET_WM_STATE_ABOVE); + if (ex_style & WS_EX_TOOLWINDOW) + new_state |= (1 << NET_WM_STATE_SKIP_TASKBAR) | (1 << NET_WM_STATE_SKIP_PAGER); + if (!(ex_style & WS_EX_APPWINDOW) && GetWindow( data->hwnd, GW_OWNER )) + new_state |= (1 << NET_WM_STATE_SKIP_TASKBAR); + + if (!data->mapped) /* set the _NET_WM_STATE atom directly */ + { + Atom atoms[NB_NET_WM_STATES+1]; + DWORD count; + + for (i = count = 0; i < NB_NET_WM_STATES; i++) + { + if (!(new_state & (1 << i))) continue; + TRACE( "setting wm state %u for unmapped window %p/%lx\n", + i, data->hwnd, data->whole_window ); + atoms[count++] = X11DRV_Atoms[state_atoms[i] - FIRST_XATOM]; + if (state_atoms[i] == XATOM__NET_WM_STATE_MAXIMIZED_VERT) + atoms[count++] = x11drv_atom(_NET_WM_STATE_MAXIMIZED_HORZ); + } + wine_tsx11_lock(); + XChangeProperty( display, data->whole_window, x11drv_atom(_NET_WM_STATE), XA_ATOM, + 32, PropModeReplace, (unsigned char *)atoms, count ); + wine_tsx11_unlock(); + } + else /* ask the window manager to do it for us */ + { + XEvent xev; + + xev.xclient.type = ClientMessage; + xev.xclient.window = data->whole_window; + xev.xclient.message_type = x11drv_atom(_NET_WM_STATE); + xev.xclient.serial = 0; + xev.xclient.display = display; + xev.xclient.send_event = True; + xev.xclient.format = 32; + xev.xclient.data.l[3] = 1; + + for (i = 0; i < NB_NET_WM_STATES; i++) + { + if (!((data->net_wm_state ^ new_state) & (1 << i))) continue; /* unchanged */ + + TRACE( "setting wm state %u for window %p/%lx to %u prev %u\n", + i, data->hwnd, data->whole_window, + (new_state & (1 << i)) != 0, (data->net_wm_state & (1 << i)) != 0 ); + + xev.xclient.data.l[0] = (new_state & (1 << i)) ? _NET_WM_STATE_ADD : _NET_WM_STATE_REMOVE; + xev.xclient.data.l[1] = X11DRV_Atoms[state_atoms[i] - FIRST_XATOM]; + xev.xclient.data.l[2] = ((state_atoms[i] == XATOM__NET_WM_STATE_MAXIMIZED_VERT) ? + x11drv_atom(_NET_WM_STATE_MAXIMIZED_HORZ) : 0); + wine_tsx11_lock(); + XSendEvent( display, root_window, False, + SubstructureRedirectMask | SubstructureNotifyMask, &xev ); + wine_tsx11_unlock(); + } + } + data->net_wm_state = new_state; +} + + +/*********************************************************************** + * set_xembed_flags + */ +static void set_xembed_flags( Display *display, struct x11drv_win_data *data, unsigned long flags ) +{ + unsigned long info[2]; + + info[0] = 0; /* protocol version */ + info[1] = flags; + wine_tsx11_lock(); + XChangeProperty( display, data->whole_window, x11drv_atom(_XEMBED_INFO), + x11drv_atom(_XEMBED_INFO), 32, PropModeReplace, (unsigned char*)info, 2 ); + wine_tsx11_unlock(); +} + + +/*********************************************************************** + * map_window + */ +static void map_window( Display *display, struct x11drv_win_data *data, DWORD new_style ) +{ + TRACE( "win %p/%lx\n", data->hwnd, data->whole_window ); + + wait_for_withdrawn_state( display, data, TRUE ); + + if (!data->embedded) + { + update_net_wm_states( display, data ); + sync_window_style( display, data ); + wine_tsx11_lock(); + XMapWindow( display, data->whole_window ); + wine_tsx11_unlock(); + } + else set_xembed_flags( display, data, XEMBED_MAPPED ); + + data->mapped = TRUE; + data->iconic = (new_style & WS_MINIMIZE) != 0; +} + + +/*********************************************************************** + * unmap_window + */ +static void unmap_window( Display *display, struct x11drv_win_data *data ) +{ + TRACE( "win %p/%lx\n", data->hwnd, data->whole_window ); + + if (!data->embedded) + { + wait_for_withdrawn_state( display, data, FALSE ); + wine_tsx11_lock(); + if (data->managed) XWithdrawWindow( display, data->whole_window, DefaultScreen(display) ); + else XUnmapWindow( display, data->whole_window ); + wine_tsx11_unlock(); + } + else set_xembed_flags( display, data, 0 ); + + data->mapped = FALSE; + data->net_wm_state = 0; +} + + +/*********************************************************************** + * make_window_embedded + */ +void make_window_embedded( Display *display, struct x11drv_win_data *data ) +{ + if (data->mapped) + { + /* the window cannot be mapped before being embedded */ + unmap_window( display, data ); + data->embedded = TRUE; + map_window( display, data, 0 ); + } + else + { + data->embedded = TRUE; + set_xembed_flags( display, data, 0 ); + } +} + + +/*********************************************************************** * X11DRV_window_to_X_rect * * Convert a rect from client to X window coordinates @@ -965,11 +1144,11 @@ void X11DRV_X_to_window_rect( struct x11drv_win_data *data, RECT *rect ) /*********************************************************************** - * X11DRV_sync_window_position + * sync_window_position * * Synchronize the X window position with the Windows one */ -void X11DRV_sync_window_position( Display *display, struct x11drv_win_data *data, +static void sync_window_position( Display *display, struct x11drv_win_data *data, UINT swp_flags, const RECT *old_client_rect, const RECT *old_whole_rect ) { @@ -1019,11 +1198,11 @@ void X11DRV_sync_window_position( Display *display, struct x11drv_win_data *data /*********************************************************************** - * X11DRV_sync_client_position + * sync_client_position * * Synchronize the X client window position with the Windows one */ -void X11DRV_sync_client_position( Display *display, struct x11drv_win_data *data, +static void sync_client_position( Display *display, struct x11drv_win_data *data, UINT swp_flags, const RECT *old_client_rect, const RECT *old_whole_rect ) { @@ -1050,6 +1229,69 @@ void X11DRV_sync_client_position( Display *display, struct x11drv_win_data *data } +/*********************************************************************** + * move_window_bits + * + * Move the window bits when a window is moved. + */ +static void move_window_bits( struct x11drv_win_data *data, const RECT *old_rect, const RECT *new_rect, + const RECT *old_client_rect ) +{ + RECT src_rect = *old_rect; + RECT dst_rect = *new_rect; + HDC hdc_src, hdc_dst; + INT code; + HRGN rgn = 0; + HWND parent = 0; + + if (!data->whole_window) + { + OffsetRect( &dst_rect, -data->window_rect.left, -data->window_rect.top ); + parent = GetAncestor( data->hwnd, GA_PARENT ); + hdc_src = GetDCEx( parent, 0, DCX_CACHE ); + hdc_dst = GetDCEx( data->hwnd, 0, DCX_CACHE | DCX_WINDOW ); + } + else + { + OffsetRect( &dst_rect, -data->client_rect.left, -data->client_rect.top ); + /* make src rect relative to the old position of the window */ + OffsetRect( &src_rect, -old_client_rect->left, -old_client_rect->top ); + if (dst_rect.left == src_rect.left && dst_rect.top == src_rect.top) return; + hdc_src = hdc_dst = GetDCEx( data->hwnd, 0, DCX_CACHE ); + } + + code = X11DRV_START_EXPOSURES; + ExtEscape( hdc_dst, X11DRV_ESCAPE, sizeof(code), (LPSTR)&code, 0, NULL ); + + TRACE( "copying bits for win %p/%lx/%lx %s -> %s\n", + data->hwnd, data->whole_window, data->client_window, + wine_dbgstr_rect(&src_rect), wine_dbgstr_rect(&dst_rect) ); + BitBlt( hdc_dst, dst_rect.left, dst_rect.top, + dst_rect.right - dst_rect.left, dst_rect.bottom - dst_rect.top, + hdc_src, src_rect.left, src_rect.top, SRCCOPY ); + + code = X11DRV_END_EXPOSURES; + ExtEscape( hdc_dst, X11DRV_ESCAPE, sizeof(code), (LPSTR)&code, sizeof(rgn), (LPSTR)&rgn ); + + ReleaseDC( data->hwnd, hdc_dst ); + if (hdc_src != hdc_dst) ReleaseDC( parent, hdc_src ); + + if (rgn) + { + if (!data->whole_window) + { + /* map region to client rect since we are using DCX_WINDOW */ + OffsetRgn( rgn, data->window_rect.left - data->client_rect.left, + data->window_rect.top - data->client_rect.top ); + RedrawWindow( data->hwnd, NULL, rgn, + RDW_INVALIDATE | RDW_FRAME | RDW_ERASE | RDW_ALLCHILDREN ); + } + else RedrawWindow( data->hwnd, NULL, rgn, RDW_INVALIDATE | RDW_ERASE | RDW_ALLCHILDREN ); + DeleteObject( rgn ); + } +} + + /********************************************************************** * create_whole_window * @@ -1099,7 +1341,7 @@ static Window create_whole_window( Display *display, struct x11drv_win_data *dat } set_initial_wm_hints( display, data ); - X11DRV_set_wm_hints( display, data ); + set_wm_hints( display, data ); SetPropA( data->hwnd, whole_window_prop, (HANDLE)data->whole_window ); @@ -1173,6 +1415,48 @@ void X11DRV_SetWindowText( HWND hwnd, LPCWSTR text ) /*********************************************************************** + * SetWindowStyle (X11DRV.@) + * + * Update the X state of a window to reflect a style change + */ +void X11DRV_SetWindowStyle( HWND hwnd, DWORD old_style ) +{ + Display *display = thread_display(); + struct x11drv_win_data *data; + DWORD new_style, changed; + + if (hwnd == GetDesktopWindow()) return; + new_style = GetWindowLongW( hwnd, GWL_STYLE ); + changed = new_style ^ old_style; + + if ((changed & WS_VISIBLE) && (new_style & WS_VISIBLE)) + { + /* we don't unmap windows, that causes trouble with the window manager */ + if (!(data = X11DRV_get_win_data( hwnd )) && + !(data = X11DRV_create_win_data( hwnd ))) return; + + if (data->whole_window && is_window_rect_mapped( &data->window_rect )) + { + set_wm_hints( display, data ); + if (!data->mapped) map_window( display, data, new_style ); + } + } + + if (changed & WS_DISABLED) + { + data = X11DRV_get_win_data( hwnd ); + if (data && data->wm_hints) + { + wine_tsx11_lock(); + data->wm_hints->input = !(new_style & WS_DISABLED); + XSetWMHints( display, data->whole_window, data->wm_hints ); + wine_tsx11_unlock(); + } + } +} + + +/*********************************************************************** * DestroyWindow (X11DRV.@) */ void X11DRV_DestroyWindow( HWND hwnd ) @@ -1604,6 +1888,145 @@ void X11DRV_SetFocus( HWND hwnd ) } +/*********************************************************************** + * SetWindowPos (X11DRV.@) + */ +void X11DRV_SetWindowPos( HWND hwnd, HWND insert_after, UINT swp_flags, + const RECT *rectWindow, const RECT *rectClient, + const RECT *visible_rect, const RECT *valid_rects ) +{ + struct x11drv_thread_data *thread_data = x11drv_thread_data(); + Display *display = thread_data->display; + struct x11drv_win_data *data = X11DRV_get_win_data( hwnd ); + DWORD new_style = GetWindowLongW( hwnd, GWL_STYLE ); + RECT old_window_rect, old_whole_rect, old_client_rect; + int event_type; + + if (!data) + { + /* create the win data if the window is being made visible */ + if (!(new_style & WS_VISIBLE)) return; + if (!(data = X11DRV_create_win_data( hwnd ))) return; + } + + /* check if we need to switch the window to managed */ + if (!data->managed && data->whole_window && is_window_managed( hwnd, swp_flags, rectWindow )) + { + TRACE( "making win %p/%lx managed\n", hwnd, data->whole_window ); + if (data->mapped) unmap_window( display, data ); + data->managed = TRUE; + SetPropA( hwnd, managed_prop, (HANDLE)1 ); + } + + old_window_rect = data->window_rect; + old_whole_rect = data->whole_rect; + old_client_rect = data->client_rect; + data->window_rect = *rectWindow; + data->whole_rect = *rectWindow; + data->client_rect = *rectClient; + X11DRV_window_to_X_rect( data, &data->whole_rect ); + if (memcmp( visible_rect, &data->whole_rect, sizeof(RECT) )) + { + TRACE( "%p: need to update visible rect %s -> %s\n", hwnd, + wine_dbgstr_rect(visible_rect), wine_dbgstr_rect(&data->whole_rect) ); + SERVER_START_REQ( set_window_visible_rect ) + { + req->handle = hwnd; + req->flags = swp_flags; + req->visible.left = data->whole_rect.left; + req->visible.top = data->whole_rect.top; + req->visible.right = data->whole_rect.right; + req->visible.bottom = data->whole_rect.bottom; + wine_server_call( req ); + } + SERVER_END_REQ; + } + + TRACE( "win %p window %s client %s style %08x flags %08x\n", + hwnd, wine_dbgstr_rect(rectWindow), wine_dbgstr_rect(rectClient), new_style, swp_flags ); + + if (!IsRectEmpty( &valid_rects[0] )) + { + int x_offset = old_whole_rect.left - data->whole_rect.left; + int y_offset = old_whole_rect.top - data->whole_rect.top; + + /* if all that happened is that the whole window moved, copy everything */ + if (!(swp_flags & SWP_FRAMECHANGED) && + old_whole_rect.right - data->whole_rect.right == x_offset && + old_whole_rect.bottom - data->whole_rect.bottom == y_offset && + old_client_rect.left - data->client_rect.left == x_offset && + old_client_rect.right - data->client_rect.right == x_offset && + old_client_rect.top - data->client_rect.top == y_offset && + old_client_rect.bottom - data->client_rect.bottom == y_offset && + !memcmp( &valid_rects[0], &data->client_rect, sizeof(RECT) )) + { + /* if we have an X window the bits will be moved by the X server */ + if (!data->whole_window) + move_window_bits( data, &old_whole_rect, &data->whole_rect, &old_client_rect ); + } + else + move_window_bits( data, &valid_rects[1], &valid_rects[0], &old_client_rect ); + } + + wine_tsx11_lock(); + XFlush( gdi_display ); /* make sure painting is done before we move the window */ + wine_tsx11_unlock(); + + sync_client_position( display, data, swp_flags, &old_client_rect, &old_whole_rect ); + + if (!data->whole_window) return; + + /* check if we are currently processing an event relevant to this window */ + event_type = 0; + if (thread_data->current_event && thread_data->current_event->xany.window == data->whole_window) + event_type = thread_data->current_event->type; + + if (event_type != ConfigureNotify && event_type != PropertyNotify) + event_type = 0; /* ignore other events */ + + if (data->mapped && (!(new_style & WS_VISIBLE) || + (!event_type && !is_window_rect_mapped( rectWindow )))) + unmap_window( display, data ); + + /* don't change position if we are about to minimize or maximize a managed window */ + if (!event_type && + !(data->managed && (swp_flags & SWP_STATECHANGED) && (new_style & (WS_MINIMIZE|WS_MAXIMIZE)))) + sync_window_position( display, data, swp_flags, &old_client_rect, &old_whole_rect ); + + if ((new_style & WS_VISIBLE) && + ((new_style & WS_MINIMIZE) || is_window_rect_mapped( rectWindow ))) + { + if (!data->mapped || (swp_flags & (SWP_FRAMECHANGED|SWP_STATECHANGED))) + set_wm_hints( display, data ); + + if (!data->mapped) + { + map_window( display, data, new_style ); + } + else if ((swp_flags & SWP_STATECHANGED) && (!data->iconic != !(new_style & WS_MINIMIZE))) + { + data->iconic = (new_style & WS_MINIMIZE) != 0; + TRACE( "changing win %p iconic state to %u\n", data->hwnd, data->iconic ); + wine_tsx11_lock(); + if (data->iconic) + XIconifyWindow( display, data->whole_window, DefaultScreen(display) ); + else if (is_window_rect_mapped( rectWindow )) + XMapWindow( display, data->whole_window ); + wine_tsx11_unlock(); + update_net_wm_states( display, data ); + } + else if (!event_type) + { + update_net_wm_states( display, data ); + } + } + + wine_tsx11_lock(); + XFlush( display ); /* make sure changes are done before we start painting again */ + wine_tsx11_unlock(); +} + + /********************************************************************** * SetWindowIcon (X11DRV.@) * diff --git a/dlls/winex11.drv/winpos.c b/dlls/winex11.drv/winpos.c deleted file mode 100644 index 2f66a21b898..00000000000 --- a/dlls/winex11.drv/winpos.c +++ /dev/null @@ -1,466 +0,0 @@ -/* - * Window position related functions. - * - * Copyright 1993, 1994, 1995, 2001 Alexandre Julliard - * Copyright 1995, 1996, 1999 Alex Korobka - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA - */ - -#include "config.h" - -#include -#include -#include - -#include "windef.h" -#include "winbase.h" -#include "wingdi.h" -#include "winuser.h" -#include "winerror.h" -#include "wine/wingdi16.h" - -#include "x11drv.h" - -#include "wine/server.h" -#include "wine/debug.h" - -WINE_DEFAULT_DEBUG_CHANNEL(x11drv); - -#define SWP_AGG_NOPOSCHANGE \ - (SWP_NOSIZE | SWP_NOMOVE | SWP_NOCLIENTSIZE | SWP_NOCLIENTMOVE | SWP_NOZORDER) - -#define _NET_WM_STATE_REMOVE 0 -#define _NET_WM_STATE_ADD 1 -#define _NET_WM_STATE_TOGGLE 2 - -static const char managed_prop[] = "__wine_x11_managed"; - -/*********************************************************************** - * update_net_wm_states - */ -void update_net_wm_states( Display *display, struct x11drv_win_data *data ) -{ - static const unsigned int state_atoms[NB_NET_WM_STATES] = - { - XATOM__NET_WM_STATE_FULLSCREEN, - XATOM__NET_WM_STATE_ABOVE, - XATOM__NET_WM_STATE_MAXIMIZED_VERT, - XATOM__NET_WM_STATE_SKIP_PAGER, - XATOM__NET_WM_STATE_SKIP_TASKBAR - }; - - DWORD i, style, ex_style, new_state = 0; - - if (!data->managed) return; - if (data->whole_window == root_window) return; - - style = GetWindowLongW( data->hwnd, GWL_STYLE ); - if (data->whole_rect.left <= 0 && data->whole_rect.right >= screen_width && - data->whole_rect.top <= 0 && data->whole_rect.bottom >= screen_height) - { - if ((style & WS_MAXIMIZE) && (style & WS_CAPTION) == WS_CAPTION) - new_state |= (1 << NET_WM_STATE_MAXIMIZED); - else if (!(style & WS_MINIMIZE)) - new_state |= (1 << NET_WM_STATE_FULLSCREEN); - } - else if (style & WS_MAXIMIZE) - new_state |= (1 << NET_WM_STATE_MAXIMIZED); - - ex_style = GetWindowLongW( data->hwnd, GWL_EXSTYLE ); - if (ex_style & WS_EX_TOPMOST) - new_state |= (1 << NET_WM_STATE_ABOVE); - if (ex_style & WS_EX_TOOLWINDOW) - new_state |= (1 << NET_WM_STATE_SKIP_TASKBAR) | (1 << NET_WM_STATE_SKIP_PAGER); - if (!(ex_style & WS_EX_APPWINDOW) && GetWindow( data->hwnd, GW_OWNER )) - new_state |= (1 << NET_WM_STATE_SKIP_TASKBAR); - - if (!data->mapped) /* set the _NET_WM_STATE atom directly */ - { - Atom atoms[NB_NET_WM_STATES+1]; - DWORD count; - - for (i = count = 0; i < NB_NET_WM_STATES; i++) - { - if (!(new_state & (1 << i))) continue; - TRACE( "setting wm state %u for unmapped window %p/%lx\n", - i, data->hwnd, data->whole_window ); - atoms[count++] = X11DRV_Atoms[state_atoms[i] - FIRST_XATOM]; - if (state_atoms[i] == XATOM__NET_WM_STATE_MAXIMIZED_VERT) - atoms[count++] = x11drv_atom(_NET_WM_STATE_MAXIMIZED_HORZ); - } - wine_tsx11_lock(); - XChangeProperty( display, data->whole_window, x11drv_atom(_NET_WM_STATE), XA_ATOM, - 32, PropModeReplace, (unsigned char *)atoms, count ); - wine_tsx11_unlock(); - } - else /* ask the window manager to do it for us */ - { - XEvent xev; - - xev.xclient.type = ClientMessage; - xev.xclient.window = data->whole_window; - xev.xclient.message_type = x11drv_atom(_NET_WM_STATE); - xev.xclient.serial = 0; - xev.xclient.display = display; - xev.xclient.send_event = True; - xev.xclient.format = 32; - xev.xclient.data.l[3] = 1; - - for (i = 0; i < NB_NET_WM_STATES; i++) - { - if (!((data->net_wm_state ^ new_state) & (1 << i))) continue; /* unchanged */ - - TRACE( "setting wm state %u for window %p/%lx to %u prev %u\n", - i, data->hwnd, data->whole_window, - (new_state & (1 << i)) != 0, (data->net_wm_state & (1 << i)) != 0 ); - - xev.xclient.data.l[0] = (new_state & (1 << i)) ? _NET_WM_STATE_ADD : _NET_WM_STATE_REMOVE; - xev.xclient.data.l[1] = X11DRV_Atoms[state_atoms[i] - FIRST_XATOM]; - xev.xclient.data.l[2] = ((state_atoms[i] == XATOM__NET_WM_STATE_MAXIMIZED_VERT) ? - x11drv_atom(_NET_WM_STATE_MAXIMIZED_HORZ) : 0); - wine_tsx11_lock(); - XSendEvent( display, root_window, False, - SubstructureRedirectMask | SubstructureNotifyMask, &xev ); - wine_tsx11_unlock(); - } - } - data->net_wm_state = new_state; -} - - -/*********************************************************************** - * set_xembed_flags - */ -static void set_xembed_flags( Display *display, struct x11drv_win_data *data, unsigned long flags ) -{ - unsigned long info[2]; - - info[0] = 0; /* protocol version */ - info[1] = flags; - wine_tsx11_lock(); - XChangeProperty( display, data->whole_window, x11drv_atom(_XEMBED_INFO), - x11drv_atom(_XEMBED_INFO), 32, PropModeReplace, (unsigned char*)info, 2 ); - wine_tsx11_unlock(); -} - - -/*********************************************************************** - * map_window - */ -static void map_window( Display *display, struct x11drv_win_data *data, DWORD new_style ) -{ - TRACE( "win %p/%lx\n", data->hwnd, data->whole_window ); - - wait_for_withdrawn_state( display, data, TRUE ); - - if (!data->embedded) - { - update_net_wm_states( display, data ); - X11DRV_sync_window_style( display, data ); - wine_tsx11_lock(); - XMapWindow( display, data->whole_window ); - wine_tsx11_unlock(); - } - else set_xembed_flags( display, data, XEMBED_MAPPED ); - - data->mapped = TRUE; - data->iconic = (new_style & WS_MINIMIZE) != 0; -} - - -/*********************************************************************** - * unmap_window - */ -static void unmap_window( Display *display, struct x11drv_win_data *data ) -{ - TRACE( "win %p/%lx\n", data->hwnd, data->whole_window ); - - if (!data->embedded) - { - wait_for_withdrawn_state( display, data, FALSE ); - wine_tsx11_lock(); - if (data->managed) XWithdrawWindow( display, data->whole_window, DefaultScreen(display) ); - else XUnmapWindow( display, data->whole_window ); - wine_tsx11_unlock(); - } - else set_xembed_flags( display, data, 0 ); - - data->mapped = FALSE; - data->net_wm_state = 0; -} - - -/*********************************************************************** - * make_window_embedded - */ -void make_window_embedded( Display *display, struct x11drv_win_data *data ) -{ - if (data->mapped) - { - /* the window cannot be mapped before being embedded */ - unmap_window( display, data ); - data->embedded = TRUE; - map_window( display, data, 0 ); - } - else - { - data->embedded = TRUE; - set_xembed_flags( display, data, 0 ); - } -} - - -/*********************************************************************** - * SetWindowStyle (X11DRV.@) - * - * Update the X state of a window to reflect a style change - */ -void X11DRV_SetWindowStyle( HWND hwnd, DWORD old_style ) -{ - Display *display = thread_display(); - struct x11drv_win_data *data; - DWORD new_style, changed; - - if (hwnd == GetDesktopWindow()) return; - new_style = GetWindowLongW( hwnd, GWL_STYLE ); - changed = new_style ^ old_style; - - if ((changed & WS_VISIBLE) && (new_style & WS_VISIBLE)) - { - /* we don't unmap windows, that causes trouble with the window manager */ - if (!(data = X11DRV_get_win_data( hwnd )) && - !(data = X11DRV_create_win_data( hwnd ))) return; - - if (data->whole_window && X11DRV_is_window_rect_mapped( &data->window_rect )) - { - X11DRV_set_wm_hints( display, data ); - if (!data->mapped) map_window( display, data, new_style ); - } - } - - if (changed & WS_DISABLED) - { - data = X11DRV_get_win_data( hwnd ); - if (data && data->wm_hints) - { - wine_tsx11_lock(); - data->wm_hints->input = !(new_style & WS_DISABLED); - XSetWMHints( display, data->whole_window, data->wm_hints ); - wine_tsx11_unlock(); - } - } -} - - -/*********************************************************************** - * move_window_bits - * - * Move the window bits when a window is moved. - */ -static void move_window_bits( struct x11drv_win_data *data, const RECT *old_rect, const RECT *new_rect, - const RECT *old_client_rect ) -{ - RECT src_rect = *old_rect; - RECT dst_rect = *new_rect; - HDC hdc_src, hdc_dst; - INT code; - HRGN rgn = 0; - HWND parent = 0; - - if (!data->whole_window) - { - OffsetRect( &dst_rect, -data->window_rect.left, -data->window_rect.top ); - parent = GetAncestor( data->hwnd, GA_PARENT ); - hdc_src = GetDCEx( parent, 0, DCX_CACHE ); - hdc_dst = GetDCEx( data->hwnd, 0, DCX_CACHE | DCX_WINDOW ); - } - else - { - OffsetRect( &dst_rect, -data->client_rect.left, -data->client_rect.top ); - /* make src rect relative to the old position of the window */ - OffsetRect( &src_rect, -old_client_rect->left, -old_client_rect->top ); - if (dst_rect.left == src_rect.left && dst_rect.top == src_rect.top) return; - hdc_src = hdc_dst = GetDCEx( data->hwnd, 0, DCX_CACHE ); - } - - code = X11DRV_START_EXPOSURES; - ExtEscape( hdc_dst, X11DRV_ESCAPE, sizeof(code), (LPSTR)&code, 0, NULL ); - - TRACE( "copying bits for win %p/%lx/%lx %s -> %s\n", - data->hwnd, data->whole_window, data->client_window, - wine_dbgstr_rect(&src_rect), wine_dbgstr_rect(&dst_rect) ); - BitBlt( hdc_dst, dst_rect.left, dst_rect.top, - dst_rect.right - dst_rect.left, dst_rect.bottom - dst_rect.top, - hdc_src, src_rect.left, src_rect.top, SRCCOPY ); - - code = X11DRV_END_EXPOSURES; - ExtEscape( hdc_dst, X11DRV_ESCAPE, sizeof(code), (LPSTR)&code, sizeof(rgn), (LPSTR)&rgn ); - - ReleaseDC( data->hwnd, hdc_dst ); - if (hdc_src != hdc_dst) ReleaseDC( parent, hdc_src ); - - if (rgn) - { - if (!data->whole_window) - { - /* map region to client rect since we are using DCX_WINDOW */ - OffsetRgn( rgn, data->window_rect.left - data->client_rect.left, - data->window_rect.top - data->client_rect.top ); - RedrawWindow( data->hwnd, NULL, rgn, - RDW_INVALIDATE | RDW_FRAME | RDW_ERASE | RDW_ALLCHILDREN ); - } - else RedrawWindow( data->hwnd, NULL, rgn, RDW_INVALIDATE | RDW_ERASE | RDW_ALLCHILDREN ); - DeleteObject( rgn ); - } -} - -/*********************************************************************** - * SetWindowPos (X11DRV.@) - */ -void X11DRV_SetWindowPos( HWND hwnd, HWND insert_after, UINT swp_flags, - const RECT *rectWindow, const RECT *rectClient, - const RECT *visible_rect, const RECT *valid_rects ) -{ - struct x11drv_thread_data *thread_data = x11drv_thread_data(); - Display *display = thread_data->display; - struct x11drv_win_data *data = X11DRV_get_win_data( hwnd ); - DWORD new_style = GetWindowLongW( hwnd, GWL_STYLE ); - RECT old_window_rect, old_whole_rect, old_client_rect; - int event_type; - - if (!data) - { - /* create the win data if the window is being made visible */ - if (!(new_style & WS_VISIBLE)) return; - if (!(data = X11DRV_create_win_data( hwnd ))) return; - } - - /* check if we need to switch the window to managed */ - if (!data->managed && data->whole_window && is_window_managed( hwnd, swp_flags, rectWindow )) - { - TRACE( "making win %p/%lx managed\n", hwnd, data->whole_window ); - if (data->mapped) unmap_window( display, data ); - data->managed = TRUE; - SetPropA( hwnd, managed_prop, (HANDLE)1 ); - } - - old_window_rect = data->window_rect; - old_whole_rect = data->whole_rect; - old_client_rect = data->client_rect; - data->window_rect = *rectWindow; - data->whole_rect = *rectWindow; - data->client_rect = *rectClient; - X11DRV_window_to_X_rect( data, &data->whole_rect ); - if (memcmp( visible_rect, &data->whole_rect, sizeof(RECT) )) - { - TRACE( "%p: need to update visible rect %s -> %s\n", hwnd, - wine_dbgstr_rect(visible_rect), wine_dbgstr_rect(&data->whole_rect) ); - SERVER_START_REQ( set_window_visible_rect ) - { - req->handle = hwnd; - req->flags = swp_flags; - req->visible.left = data->whole_rect.left; - req->visible.top = data->whole_rect.top; - req->visible.right = data->whole_rect.right; - req->visible.bottom = data->whole_rect.bottom; - wine_server_call( req ); - } - SERVER_END_REQ; - } - - TRACE( "win %p window %s client %s style %08x flags %08x\n", - hwnd, wine_dbgstr_rect(rectWindow), wine_dbgstr_rect(rectClient), new_style, swp_flags ); - - if (!IsRectEmpty( &valid_rects[0] )) - { - int x_offset = old_whole_rect.left - data->whole_rect.left; - int y_offset = old_whole_rect.top - data->whole_rect.top; - - /* if all that happened is that the whole window moved, copy everything */ - if (!(swp_flags & SWP_FRAMECHANGED) && - old_whole_rect.right - data->whole_rect.right == x_offset && - old_whole_rect.bottom - data->whole_rect.bottom == y_offset && - old_client_rect.left - data->client_rect.left == x_offset && - old_client_rect.right - data->client_rect.right == x_offset && - old_client_rect.top - data->client_rect.top == y_offset && - old_client_rect.bottom - data->client_rect.bottom == y_offset && - !memcmp( &valid_rects[0], &data->client_rect, sizeof(RECT) )) - { - /* if we have an X window the bits will be moved by the X server */ - if (!data->whole_window) - move_window_bits( data, &old_whole_rect, &data->whole_rect, &old_client_rect ); - } - else - move_window_bits( data, &valid_rects[1], &valid_rects[0], &old_client_rect ); - } - - wine_tsx11_lock(); - XFlush( gdi_display ); /* make sure painting is done before we move the window */ - wine_tsx11_unlock(); - - X11DRV_sync_client_position( display, data, swp_flags, &old_client_rect, &old_whole_rect ); - - if (!data->whole_window) return; - - /* check if we are currently processing an event relevant to this window */ - event_type = 0; - if (thread_data->current_event && thread_data->current_event->xany.window == data->whole_window) - event_type = thread_data->current_event->type; - - if (event_type != ConfigureNotify && event_type != PropertyNotify) - event_type = 0; /* ignore other events */ - - if (data->mapped && (!(new_style & WS_VISIBLE) || - (!event_type && !X11DRV_is_window_rect_mapped( rectWindow )))) - unmap_window( display, data ); - - /* don't change position if we are about to minimize or maximize a managed window */ - if (!event_type && - !(data->managed && (swp_flags & SWP_STATECHANGED) && (new_style & (WS_MINIMIZE|WS_MAXIMIZE)))) - X11DRV_sync_window_position( display, data, swp_flags, &old_client_rect, &old_whole_rect ); - - if ((new_style & WS_VISIBLE) && - ((new_style & WS_MINIMIZE) || X11DRV_is_window_rect_mapped( rectWindow ))) - { - if (!data->mapped || (swp_flags & (SWP_FRAMECHANGED|SWP_STATECHANGED))) - X11DRV_set_wm_hints( display, data ); - - if (!data->mapped) - { - map_window( display, data, new_style ); - } - else if ((swp_flags & SWP_STATECHANGED) && (!data->iconic != !(new_style & WS_MINIMIZE))) - { - data->iconic = (new_style & WS_MINIMIZE) != 0; - TRACE( "changing win %p iconic state to %u\n", data->hwnd, data->iconic ); - wine_tsx11_lock(); - if (data->iconic) - XIconifyWindow( display, data->whole_window, DefaultScreen(display) ); - else if (X11DRV_is_window_rect_mapped( rectWindow )) - XMapWindow( display, data->whole_window ); - wine_tsx11_unlock(); - update_net_wm_states( display, data ); - } - else if (!event_type) - { - update_net_wm_states( display, data ); - } - } - - wine_tsx11_lock(); - XFlush( display ); /* make sure changes are done before we start painting again */ - wine_tsx11_unlock(); -} diff --git a/dlls/winex11.drv/x11drv.h b/dlls/winex11.drv/x11drv.h index f40445b8f4e..f46eaaa4ad1 100644 --- a/dlls/winex11.drv/x11drv.h +++ b/dlls/winex11.drv/x11drv.h @@ -548,6 +548,7 @@ extern int dxgrab; extern int use_xkb; extern int use_take_focus; extern int use_primary_selection; +extern int usexcomposite; extern int managed_mode; extern int decorated_mode; extern int private_color_map; @@ -699,7 +700,6 @@ extern struct x11drv_win_data *X11DRV_get_win_data( HWND hwnd ); extern struct x11drv_win_data *X11DRV_create_win_data( HWND hwnd ); extern Window X11DRV_get_whole_window( HWND hwnd ); extern Window X11DRV_get_client_window( HWND hwnd ); -extern BOOL X11DRV_is_window_rect_mapped( const RECT *rect ); extern XIC X11DRV_get_ic( HWND hwnd ); extern BOOL X11DRV_set_win_format( HWND hwnd, XID fbconfig ); @@ -709,7 +709,6 @@ extern void mark_drawable_dirty( Drawable old, Drawable new ); extern Drawable create_glxpixmap( Display *display, XVisualInfo *vis, Pixmap parent ); extern void flush_gl_drawable( X11DRV_PDEVICE *physDev ); -extern int get_window_wm_state( Display *display, struct x11drv_win_data *data ); extern void wait_for_withdrawn_state( Display *display, struct x11drv_win_data *data, BOOL set ); extern void update_net_wm_states( Display *display, struct x11drv_win_data *data ); extern void make_window_embedded( Display *display, struct x11drv_win_data *data ); @@ -736,17 +735,8 @@ typedef int (*x11drv_error_callback)( Display *display, XErrorEvent *event, void extern void X11DRV_expect_error( Display *display, x11drv_error_callback callback, void *arg ); extern int X11DRV_check_error(void); -extern BOOL is_window_managed( HWND hwnd, UINT swp_flags, const RECT *window_rect ); extern void X11DRV_window_to_X_rect( struct x11drv_win_data *data, 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, - UINT swp_flags, const RECT *old_client_rect, - const RECT *old_whole_rect ); -extern void X11DRV_sync_client_position( Display *display, struct x11drv_win_data *data, - UINT swp_flags, const RECT *old_client_rect, - const RECT *old_whole_rect ); -extern void X11DRV_set_wm_hints( Display *display, struct x11drv_win_data *data ); extern void xinerama_init( unsigned int width, unsigned int height ); extern void X11DRV_init_desktop( Window win, unsigned int width, unsigned int height ); -- 2.11.4.GIT