blob: b85aff05e67c3facf02d4c88b2238652eccc6324 [file] [log] [blame]
Alexandre Julliard9ae0fe52001-04-24 23:28:52 +00001/*
2 * Window related functions
3 *
4 * Copyright 1993, 1994, 1995, 1996, 2001 Alexandre Julliard
5 * Copyright 1993 David Metcalfe
6 * Copyright 1995, 1996 Alex Korobka
Alexandre Julliard0799c1a2002-03-09 23:29:33 +00007 *
8 * This library is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU Lesser General Public
10 * License as published by the Free Software Foundation; either
11 * version 2.1 of the License, or (at your option) any later version.
12 *
13 * This library is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 * Lesser General Public License for more details.
17 *
18 * You should have received a copy of the GNU Lesser General Public
19 * License along with this library; if not, write to the Free Software
Jonathan Ernst360a3f92006-05-18 14:49:52 +020020 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
Alexandre Julliard9ae0fe52001-04-24 23:28:52 +000021 */
22
23#include "config.h"
24
Alexandre Julliarde37c6e12003-09-05 23:08:26 +000025#include <stdarg.h>
Dmitry Timoshkovde70d2b2001-06-19 03:32:44 +000026#include <stdlib.h>
James Liggett60a97502006-08-22 17:14:11 -070027#include <stdio.h>
Patrik Stridvallba78aac2003-08-08 21:07:23 +000028#ifdef HAVE_UNISTD_H
29# include <unistd.h>
30#endif
Dmitry Timoshkovde70d2b2001-06-19 03:32:44 +000031
Alexandre Julliard64c0e2a2003-11-21 21:48:36 +000032#include <X11/Xlib.h>
Alexandre Julliarde9119c12002-09-24 18:36:51 +000033#include <X11/Xresource.h>
34#include <X11/Xutil.h>
Alexandre Julliard395928d2008-01-23 16:30:18 +010035#ifdef HAVE_LIBXSHAPE
36#include <X11/extensions/shape.h>
37#endif /* HAVE_LIBXSHAPE */
Alexandre Julliard9ae0fe52001-04-24 23:28:52 +000038
Alexandre Julliarde37c6e12003-09-05 23:08:26 +000039#include "windef.h"
Alexandre Julliard9ae0fe52001-04-24 23:28:52 +000040#include "winbase.h"
41#include "wingdi.h"
42#include "winuser.h"
Ilya Konstantinov560ca322001-10-02 18:44:56 +000043#include "wine/unicode.h"
Alexandre Julliard9ae0fe52001-04-24 23:28:52 +000044
Alexandre Julliard9ae0fe52001-04-24 23:28:52 +000045#include "x11drv.h"
Chris Robinson00633e32007-09-25 22:43:38 -070046#include "xcomposite.h"
Alexandre Julliard4d32a472005-03-25 10:38:56 +000047#include "wine/debug.h"
48#include "wine/server.h"
Ove Kaaven77e7fd72002-01-21 18:41:27 +000049#include "mwm.h"
Alexandre Julliard9ae0fe52001-04-24 23:28:52 +000050
Alexandre Julliard0799c1a2002-03-09 23:29:33 +000051WINE_DEFAULT_DEBUG_CHANNEL(x11drv);
Alexandre Julliard9ae0fe52001-04-24 23:28:52 +000052
Alexandre Julliard24dbaa02008-04-17 16:13:34 +020053#define _NET_WM_MOVERESIZE_SIZE_TOPLEFT 0
54#define _NET_WM_MOVERESIZE_SIZE_TOP 1
55#define _NET_WM_MOVERESIZE_SIZE_TOPRIGHT 2
56#define _NET_WM_MOVERESIZE_SIZE_RIGHT 3
57#define _NET_WM_MOVERESIZE_SIZE_BOTTOMRIGHT 4
58#define _NET_WM_MOVERESIZE_SIZE_BOTTOM 5
59#define _NET_WM_MOVERESIZE_SIZE_BOTTOMLEFT 6
60#define _NET_WM_MOVERESIZE_SIZE_LEFT 7
61#define _NET_WM_MOVERESIZE_MOVE 8
62#define _NET_WM_MOVERESIZE_SIZE_KEYBOARD 9
63#define _NET_WM_MOVERESIZE_MOVE_KEYBOARD 10
64
Alexandre Julliard855308f2008-04-23 15:32:58 +020065#define _NET_WM_STATE_REMOVE 0
66#define _NET_WM_STATE_ADD 1
67#define _NET_WM_STATE_TOGGLE 2
68
69#define SWP_AGG_NOPOSCHANGE (SWP_NOSIZE | SWP_NOMOVE | SWP_NOCLIENTSIZE | SWP_NOCLIENTMOVE | SWP_NOZORDER)
70
Alexandre Julliard9ae0fe52001-04-24 23:28:52 +000071/* X context to associate a hwnd to an X window */
72XContext winContext = 0;
73
Alexandre Julliardd56ccaa2005-01-28 17:25:50 +000074/* X context to associate a struct x11drv_win_data to an hwnd */
75static XContext win_data_context;
76
Alexandre Julliardaf50ad62005-07-07 17:30:57 +000077static const char whole_window_prop[] = "__wine_x11_whole_window";
Alexandre Julliard8ee07d42008-02-21 12:29:36 +010078static const char client_window_prop[]= "__wine_x11_client_window";
Alexandre Julliardaf50ad62005-07-07 17:30:57 +000079static const char icon_window_prop[] = "__wine_x11_icon_window";
Chris Robinsond9571c92007-09-15 13:02:32 -070080static const char fbconfig_id_prop[] = "__wine_x11_fbconfig_id";
Chris Robinsona8124f92007-09-25 10:20:58 -070081static const char gl_drawable_prop[] = "__wine_x11_gl_drawable";
Chris Robinson37d835b2007-09-26 08:17:13 -070082static const char pixmap_prop[] = "__wine_x11_pixmap";
Alexandre Julliardaf50ad62005-07-07 17:30:57 +000083static const char managed_prop[] = "__wine_x11_managed";
Alexandre Julliard9ae0fe52001-04-24 23:28:52 +000084
Damjan Jovanovic3613b152009-01-06 20:59:07 +020085
86/***********************************************************************
87 * http://standards.freedesktop.org/startup-notification-spec
88 */
89static void remove_startup_notification(Display *display, Window window)
90{
91 static LONG startup_notification_removed = 0;
92 char id[1024];
93 char message[1024];
94 int i;
95 int pos;
96 XEvent xevent;
97 const char *src;
98 int srclen;
99
100 if (InterlockedCompareExchange(&startup_notification_removed, 1, 0) != 0)
101 return;
102
103 if (GetEnvironmentVariableA("DESKTOP_STARTUP_ID", id, sizeof(id)) == 0)
104 return;
105 SetEnvironmentVariableA("DESKTOP_STARTUP_ID", NULL);
106
107 pos = snprintf(message, sizeof(message), "remove: ID=");
108 message[pos++] = '"';
109 for (i = 0; id[i] && pos < sizeof(message) - 2; i++)
110 {
111 if (id[i] == '"' || id[i] == '\\')
112 message[pos++] = '\\';
113 message[pos++] = id[i];
114 }
115 message[pos++] = '"';
116 message[pos++] = '\0';
117
118 xevent.xclient.type = ClientMessage;
119 xevent.xclient.message_type = x11drv_atom(_NET_STARTUP_INFO_BEGIN);
120 xevent.xclient.display = display;
121 xevent.xclient.window = window;
122 xevent.xclient.format = 8;
123
124 src = message;
125 srclen = strlen(src) + 1;
126
127 wine_tsx11_lock();
128 while (srclen > 0)
129 {
130 int msglen = srclen;
131 if (msglen > 20)
132 msglen = 20;
133 memset(&xevent.xclient.data.b[0], 0, 20);
134 memcpy(&xevent.xclient.data.b[0], src, msglen);
135 src += msglen;
136 srclen -= msglen;
137
138 XSendEvent( display, DefaultRootWindow( display ), False, PropertyChangeMask, &xevent );
139 xevent.xclient.message_type = x11drv_atom(_NET_STARTUP_INFO);
140 }
141 wine_tsx11_unlock();
142}
143
144
Alexandre Julliard391afac2010-02-23 12:34:19 +0100145struct has_popup_result
146{
147 HWND hwnd;
148 BOOL found;
149};
150
151static BOOL CALLBACK has_popup( HWND hwnd, LPARAM lparam )
152{
153 struct has_popup_result *result = (struct has_popup_result *)lparam;
154
155 if (hwnd == result->hwnd) return FALSE; /* popups are always above owner */
156 result->found = (GetWindow( hwnd, GW_OWNER ) == result->hwnd);
157 return !result->found;
158}
159
160static BOOL has_owned_popups( HWND hwnd )
161{
162 struct has_popup_result result;
163
164 result.hwnd = hwnd;
165 result.found = FALSE;
166 EnumWindows( has_popup, (LPARAM)&result );
167 return result.found;
168}
169
Alexandre Julliard9ae0fe52001-04-24 23:28:52 +0000170/***********************************************************************
Alexandre Julliarddc4fe772001-06-04 21:55:17 +0000171 * is_window_managed
Alexandre Julliard9ae0fe52001-04-24 23:28:52 +0000172 *
Alexandre Julliarddc4fe772001-06-04 21:55:17 +0000173 * Check if a given window should be managed
Alexandre Julliard9ae0fe52001-04-24 23:28:52 +0000174 */
Alexandre Julliard855308f2008-04-23 15:32:58 +0200175static BOOL is_window_managed( HWND hwnd, UINT swp_flags, const RECT *window_rect )
Alexandre Julliard9ae0fe52001-04-24 23:28:52 +0000176{
Alexandre Julliardfc5ce142005-01-17 19:17:47 +0000177 DWORD style, ex_style;
178
Alexandre Julliard89131822008-01-24 10:21:07 +0100179 if (!managed_mode) return FALSE;
180
Alexandre Julliarddc4fe772001-06-04 21:55:17 +0000181 /* child windows are not managed */
Alexandre Julliardfc5ce142005-01-17 19:17:47 +0000182 style = GetWindowLongW( hwnd, GWL_STYLE );
Peter Dons Tychsend0b21ab2007-07-25 04:09:50 +0200183 if ((style & (WS_CHILD|WS_POPUP)) == WS_CHILD) return FALSE;
Alexandre Julliardeffdfa72007-08-27 12:37:14 +0200184 /* activated windows are managed */
185 if (!(swp_flags & (SWP_NOACTIVATE|SWP_HIDEWINDOW))) return TRUE;
186 if (hwnd == GetActiveWindow()) return TRUE;
Mike Hearn27d972f2003-12-04 21:54:13 +0000187 /* windows with caption are managed */
Alexandre Julliardfc5ce142005-01-17 19:17:47 +0000188 if ((style & WS_CAPTION) == WS_CAPTION) return TRUE;
Mike Hearn27d972f2003-12-04 21:54:13 +0000189 /* windows with thick frame are managed */
Alexandre Julliardfc5ce142005-01-17 19:17:47 +0000190 if (style & WS_THICKFRAME) return TRUE;
Alexandre Julliardfc5ce142005-01-17 19:17:47 +0000191 if (style & WS_POPUP)
Alex Pasadynd18c8ca2004-02-06 05:17:55 +0000192 {
Dmitry Timoshkov15c82062008-10-07 12:14:52 +0900193 HMONITOR hmon;
194 MONITORINFO mi;
195
Vitaliy Margolenabcbcc32007-02-10 10:40:50 -0700196 /* popup with sysmenu == caption are managed */
197 if (style & WS_SYSMENU) return TRUE;
198 /* full-screen popup windows are managed */
Dmitry Timoshkov15c82062008-10-07 12:14:52 +0900199 hmon = MonitorFromWindow( hwnd, MONITOR_DEFAULTTOPRIMARY );
200 mi.cbSize = sizeof( mi );
201 GetMonitorInfoW( hmon, &mi );
202 if (window_rect->left <= mi.rcWork.left && window_rect->right >= mi.rcWork.right &&
203 window_rect->top <= mi.rcWork.top && window_rect->bottom >= mi.rcWork.bottom)
Alexandre Julliardfc5ce142005-01-17 19:17:47 +0000204 return TRUE;
Alex Pasadynd18c8ca2004-02-06 05:17:55 +0000205 }
Alexandre Julliard1f99d802008-04-25 14:26:52 +0200206 /* application windows are managed */
207 ex_style = GetWindowLongW( hwnd, GWL_EXSTYLE );
208 if (ex_style & WS_EX_APPWINDOW) return TRUE;
Alexandre Julliard391afac2010-02-23 12:34:19 +0100209 /* windows that own popups are managed */
210 if (has_owned_popups( hwnd )) return TRUE;
Alexandre Julliarddc4fe772001-06-04 21:55:17 +0000211 /* default: not managed */
212 return FALSE;
Alexandre Julliard9ae0fe52001-04-24 23:28:52 +0000213}
214
215
216/***********************************************************************
Alexandre Julliard59b7d342004-04-27 23:32:01 +0000217 * X11DRV_is_window_rect_mapped
218 *
219 * Check if the X whole window should be mapped based on its rectangle
220 */
Alexandre Julliard855308f2008-04-23 15:32:58 +0200221static BOOL is_window_rect_mapped( const RECT *rect )
Alexandre Julliard59b7d342004-04-27 23:32:01 +0000222{
Alexandre Julliard8a5f5782008-05-01 17:44:56 +0200223 /* don't map if rect is empty */
224 if (IsRectEmpty( rect )) return FALSE;
225
Alexandre Julliard59b7d342004-04-27 23:32:01 +0000226 /* don't map if rect is off-screen */
Alexandre Julliard3c305f92006-10-23 14:37:17 +0200227 if (rect->left >= virtual_screen_rect.right ||
228 rect->top >= virtual_screen_rect.bottom ||
229 rect->right <= virtual_screen_rect.left ||
230 rect->bottom <= virtual_screen_rect.top)
231 return FALSE;
Alexandre Julliard59b7d342004-04-27 23:32:01 +0000232
233 return TRUE;
234}
235
236
237/***********************************************************************
Alexandre Julliard4d14adf2008-04-04 11:25:48 +0200238 * is_window_resizable
239 *
240 * Check if window should be made resizable by the window manager
241 */
242static inline BOOL is_window_resizable( struct x11drv_win_data *data, DWORD style )
243{
244 if (style & WS_THICKFRAME) return TRUE;
245 /* Metacity needs the window to be resizable to make it fullscreen */
246 return (data->whole_rect.left <= 0 && data->whole_rect.right >= screen_width &&
247 data->whole_rect.top <= 0 && data->whole_rect.bottom >= screen_height);
248}
249
250
251/***********************************************************************
Alexandre Julliard8a5f5782008-05-01 17:44:56 +0200252 * get_window_owner
253 */
254static HWND get_window_owner( HWND hwnd )
255{
256 RECT rect;
257 HWND owner = GetWindow( hwnd, GW_OWNER );
258 /* ignore the zero-size owners used by Delphi apps */
259 if (owner && GetWindowRect( owner, &rect ) && IsRectEmpty( &rect )) owner = 0;
260 return owner;
261}
262
263
264/***********************************************************************
Alexandre Julliardc4e20e72007-10-11 12:24:27 +0200265 * get_mwm_decorations
266 */
Dmitry Timoshkov15c0bcb2008-04-16 16:50:29 +0900267static unsigned long get_mwm_decorations( struct x11drv_win_data *data,
268 DWORD style, DWORD ex_style )
Alexandre Julliardc4e20e72007-10-11 12:24:27 +0200269{
270 unsigned long ret = 0;
271
Dmitry Timoshkov15c0bcb2008-04-16 16:50:29 +0900272 if (!decorated_mode) return 0;
273
274 if (IsRectEmpty( &data->window_rect )) return 0;
Alexandre Julliard2bbf00e2008-04-29 12:46:16 +0200275 if (data->shaped) return 0;
Matthew D'Asaro4217fcb2008-04-10 12:53:45 -0700276
Alexandre Julliardc4e20e72007-10-11 12:24:27 +0200277 if (ex_style & WS_EX_TOOLWINDOW) return 0;
278
279 if ((style & WS_CAPTION) == WS_CAPTION)
280 {
281 ret |= MWM_DECOR_TITLE | MWM_DECOR_BORDER;
282 if (style & WS_SYSMENU) ret |= MWM_DECOR_MENU;
283 if (style & WS_MINIMIZEBOX) ret |= MWM_DECOR_MINIMIZE;
284 if (style & WS_MAXIMIZEBOX) ret |= MWM_DECOR_MAXIMIZE;
285 }
286 if (ex_style & WS_EX_DLGMODALFRAME) ret |= MWM_DECOR_BORDER;
287 else if (style & WS_THICKFRAME) ret |= MWM_DECOR_BORDER | MWM_DECOR_RESIZEH;
288 else if ((style & (WS_DLGFRAME|WS_BORDER)) == WS_DLGFRAME) ret |= MWM_DECOR_BORDER;
Alexandre Julliardc4e20e72007-10-11 12:24:27 +0200289 return ret;
290}
291
292
293/***********************************************************************
294 * get_x11_rect_offset
295 *
296 * Helper for X11DRV_window_to_X_rect and X11DRV_X_to_window_rect.
297 */
298static void get_x11_rect_offset( struct x11drv_win_data *data, RECT *rect )
299{
300 DWORD style, ex_style, style_mask = 0, ex_style_mask = 0;
301 unsigned long decor;
302
303 rect->top = rect->bottom = rect->left = rect->right = 0;
304
305 style = GetWindowLongW( data->hwnd, GWL_STYLE );
306 ex_style = GetWindowLongW( data->hwnd, GWL_EXSTYLE );
Dmitry Timoshkov15c0bcb2008-04-16 16:50:29 +0900307 decor = get_mwm_decorations( data, style, ex_style );
Alexandre Julliardc4e20e72007-10-11 12:24:27 +0200308
309 if (decor & MWM_DECOR_TITLE) style_mask |= WS_CAPTION;
310 if (decor & MWM_DECOR_BORDER)
311 {
312 style_mask |= WS_DLGFRAME | WS_THICKFRAME;
313 ex_style_mask |= WS_EX_DLGMODALFRAME;
314 }
315
316 AdjustWindowRectEx( rect, style & style_mask, FALSE, ex_style & ex_style_mask );
317}
318
319
320/***********************************************************************
Alexandre Julliarddc4fe772001-06-04 21:55:17 +0000321 * get_window_attributes
322 *
Alexandre Julliard883cff42001-06-12 04:02:10 +0000323 * Fill the window attributes structure for an X window.
Alexandre Julliarddc4fe772001-06-04 21:55:17 +0000324 */
Alexandre Julliard6bb18e22006-03-27 15:33:43 +0200325static int get_window_attributes( Display *display, struct x11drv_win_data *data,
326 XSetWindowAttributes *attr )
Alexandre Julliarddc4fe772001-06-04 21:55:17 +0000327{
Alexandre Julliardd7726c32005-02-01 18:53:59 +0000328 attr->override_redirect = !data->managed;
Alexandre Julliarddc4fe772001-06-04 21:55:17 +0000329 attr->colormap = X11DRV_PALETTE_PaletteXColormap;
Alexandre Julliardfc5ce142005-01-17 19:17:47 +0000330 attr->save_under = ((GetClassLongW( data->hwnd, GCL_STYLE ) & CS_SAVEBITS) != 0);
Alexandre Julliard0ce71872007-08-20 14:23:10 +0200331 attr->bit_gravity = NorthWestGravity;
Alexandre Julliard6ba06fa2008-04-23 15:33:29 +0200332 attr->win_gravity = StaticGravity;
Alexandre Julliard0ce71872007-08-20 14:23:10 +0200333 attr->backing_store = NotUseful;
334 attr->event_mask = (ExposureMask | PointerMotionMask |
335 ButtonPressMask | ButtonReleaseMask | EnterWindowMask |
Vincent Povirk538cf8b2008-12-15 18:47:24 -0600336 KeyPressMask | KeyReleaseMask | FocusChangeMask |
337 KeymapStateMask | StructureNotifyMask);
338 if (data->managed) attr->event_mask |= PropertyChangeMask;
Alexandre Julliard0ce71872007-08-20 14:23:10 +0200339
Alexandre Julliardeed9c632010-04-20 20:52:17 +0200340 return (CWOverrideRedirect | CWSaveUnder | CWColormap |
Alexandre Julliard0ce71872007-08-20 14:23:10 +0200341 CWEventMask | CWBitGravity | CWBackingStore);
Alexandre Julliard883cff42001-06-12 04:02:10 +0000342}
Alexandre Julliarddc4fe772001-06-04 21:55:17 +0000343
Alexandre Julliard883cff42001-06-12 04:02:10 +0000344
345/***********************************************************************
Alexandre Julliard42ad3452008-02-22 10:40:22 +0100346 * create_client_window
347 */
348static Window create_client_window( Display *display, struct x11drv_win_data *data, XVisualInfo *vis )
349{
350 int cx, cy, mask;
351 XSetWindowAttributes attr;
352 Window client;
Alexandre Julliard30a133f2008-05-13 10:43:48 +0200353 Visual *client_visual = vis ? vis->visual : visual;
Alexandre Julliard42ad3452008-02-22 10:40:22 +0100354
355 attr.bit_gravity = NorthWestGravity;
356 attr.win_gravity = NorthWestGravity;
357 attr.backing_store = NotUseful;
358 attr.event_mask = (ExposureMask | PointerMotionMask |
359 ButtonPressMask | ButtonReleaseMask | EnterWindowMask);
360 mask = CWEventMask | CWBitGravity | CWWinGravity | CWBackingStore;
361
362 if ((cx = data->client_rect.right - data->client_rect.left) <= 0) cx = 1;
Alexandre Julliarda4644f12009-05-05 15:36:25 +0200363 else if (cx > 65535) cx = 65535;
Alexandre Julliard42ad3452008-02-22 10:40:22 +0100364 if ((cy = data->client_rect.bottom - data->client_rect.top) <= 0) cy = 1;
Alexandre Julliarda4644f12009-05-05 15:36:25 +0200365 else if (cy > 65535) cy = 65535;
Alexandre Julliard42ad3452008-02-22 10:40:22 +0100366
367 wine_tsx11_lock();
368
369 if (vis)
370 {
371 attr.colormap = XCreateColormap( display, root_window, vis->visual,
372 (vis->class == PseudoColor || vis->class == GrayScale ||
373 vis->class == DirectColor) ? AllocAll : AllocNone );
374 mask |= CWColormap;
375 }
376
377 client = XCreateWindow( display, data->whole_window,
378 data->client_rect.left - data->whole_rect.left,
379 data->client_rect.top - data->whole_rect.top,
380 cx, cy, 0, screen_depth, InputOutput,
Alexandre Julliard30a133f2008-05-13 10:43:48 +0200381 client_visual, mask, &attr );
Alexandre Julliard42ad3452008-02-22 10:40:22 +0100382 if (!client)
383 {
384 wine_tsx11_unlock();
385 return 0;
386 }
387
388 if (data->client_window)
389 {
390 XDeleteContext( display, data->client_window, winContext );
391 XDestroyWindow( display, data->client_window );
392 }
393 data->client_window = client;
Alexandre Julliard30a133f2008-05-13 10:43:48 +0200394 data->visualid = XVisualIDFromVisual( client_visual );
Alexandre Julliard42ad3452008-02-22 10:40:22 +0100395
396 if (data->colormap) XFreeColormap( display, data->colormap );
397 data->colormap = vis ? attr.colormap : 0;
398
399 XMapWindow( display, data->client_window );
400 XSaveContext( display, data->client_window, winContext, (char *)data->hwnd );
401 wine_tsx11_unlock();
402
403 SetPropA( data->hwnd, client_window_prop, (HANDLE)data->client_window );
404 return data->client_window;
405}
406
407
408/***********************************************************************
Alexandre Julliard855308f2008-04-23 15:32:58 +0200409 * sync_window_style
Alexandre Julliard883cff42001-06-12 04:02:10 +0000410 *
411 * Change the X window attributes when the window style has changed.
412 */
Alexandre Julliard855308f2008-04-23 15:32:58 +0200413static void sync_window_style( Display *display, struct x11drv_win_data *data )
Alexandre Julliard883cff42001-06-12 04:02:10 +0000414{
Alexandre Julliard0ce71872007-08-20 14:23:10 +0200415 if (data->whole_window != root_window)
416 {
417 XSetWindowAttributes attr;
418 int mask = get_window_attributes( display, data, &attr );
Alexandre Julliard883cff42001-06-12 04:02:10 +0000419
Alexandre Julliard0ce71872007-08-20 14:23:10 +0200420 wine_tsx11_lock();
Alexandre Julliard6d5f5442006-03-06 21:02:59 +0100421 XChangeWindowAttributes( display, data->whole_window, mask, &attr );
Alexandre Julliard0ce71872007-08-20 14:23:10 +0200422 wine_tsx11_unlock();
423 }
Alexandre Julliarddc4fe772001-06-04 21:55:17 +0000424}
425
426
427/***********************************************************************
Alexandre Julliard1afd0df2010-05-10 12:33:59 +0200428 * sync_window_cursor
429 */
430static void sync_window_cursor( struct x11drv_win_data *data )
431{
432 HCURSOR cursor;
433
434 SERVER_START_REQ( set_cursor )
435 {
436 req->flags = 0;
437 wine_server_call( req );
438 cursor = reply->prev_count >= 0 ? wine_server_ptr_handle( reply->prev_handle ) : 0;
439 }
440 SERVER_END_REQ;
441
442 set_window_cursor( data->hwnd, cursor );
443}
444
445
446/***********************************************************************
Alexandre Julliard395928d2008-01-23 16:30:18 +0100447 * sync_window_region
448 *
449 * Update the X11 window region.
450 */
Alexandre Julliard9d45cfd2008-09-08 15:51:08 +0200451static void sync_window_region( Display *display, struct x11drv_win_data *data, HRGN win_region )
Alexandre Julliard395928d2008-01-23 16:30:18 +0100452{
453#ifdef HAVE_LIBXSHAPE
Alexandre Julliard9d45cfd2008-09-08 15:51:08 +0200454 HRGN hrgn = win_region;
455
Alexandre Julliard395928d2008-01-23 16:30:18 +0100456 if (!data->whole_window) return;
Alexandre Julliard2bbf00e2008-04-29 12:46:16 +0200457 data->shaped = FALSE;
Alexandre Julliard395928d2008-01-23 16:30:18 +0100458
Alexandre Julliard9d45cfd2008-09-08 15:51:08 +0200459 if (hrgn == (HRGN)1) /* hack: win_region == 1 means retrieve region from server */
460 {
461 if (!(hrgn = CreateRectRgn( 0, 0, 0, 0 ))) return;
462 if (GetWindowRgn( data->hwnd, hrgn ) == ERROR)
463 {
464 DeleteObject( hrgn );
465 hrgn = 0;
466 }
467 }
468
Alexandre Julliard395928d2008-01-23 16:30:18 +0100469 if (!hrgn)
470 {
471 wine_tsx11_lock();
472 XShapeCombineMask( display, data->whole_window, ShapeBounding, 0, 0, None, ShapeSet );
473 wine_tsx11_unlock();
474 }
475 else
476 {
477 RGNDATA *pRegionData = X11DRV_GetRegionData( hrgn, 0 );
478 if (pRegionData)
479 {
480 wine_tsx11_lock();
481 XShapeCombineRectangles( display, data->whole_window, ShapeBounding,
482 data->window_rect.left - data->whole_rect.left,
483 data->window_rect.top - data->whole_rect.top,
484 (XRectangle *)pRegionData->Buffer,
485 pRegionData->rdh.nCount, ShapeSet, YXBanded );
486 wine_tsx11_unlock();
487 HeapFree(GetProcessHeap(), 0, pRegionData);
Alexandre Julliard2bbf00e2008-04-29 12:46:16 +0200488 data->shaped = TRUE;
Alexandre Julliard395928d2008-01-23 16:30:18 +0100489 }
490 }
Alexandre Julliard9d45cfd2008-09-08 15:51:08 +0200491 if (hrgn && hrgn != win_region) DeleteObject( hrgn );
Alexandre Julliard395928d2008-01-23 16:30:18 +0100492#endif /* HAVE_LIBXSHAPE */
493}
494
495
496/***********************************************************************
Alexandre Julliardbe3c3a52008-09-12 15:54:02 +0200497 * sync_window_opacity
498 */
499static void sync_window_opacity( Display *display, Window win,
500 COLORREF key, BYTE alpha, DWORD flags )
501{
502 unsigned long opacity = 0xffffffff;
503
504 if (flags & LWA_ALPHA) opacity = (0xffffffff / 0xff) * alpha;
505
506 if (flags & LWA_COLORKEY) FIXME("LWA_COLORKEY not supported\n");
507
508 wine_tsx11_lock();
509 if (opacity == 0xffffffff)
510 XDeleteProperty( display, win, x11drv_atom(_NET_WM_WINDOW_OPACITY) );
511 else
512 XChangeProperty( display, win, x11drv_atom(_NET_WM_WINDOW_OPACITY),
513 XA_CARDINAL, 32, PropModeReplace, (unsigned char *)&opacity, 1 );
514 wine_tsx11_unlock();
515}
516
517
518/***********************************************************************
Alexandre Julliard3ba20252008-01-23 16:32:55 +0100519 * sync_window_text
520 */
521static void sync_window_text( Display *display, Window win, const WCHAR *text )
522{
523 UINT count;
524 char *buffer, *utf8_buffer;
525 XTextProperty prop;
526
527 /* allocate new buffer for window text */
528 count = WideCharToMultiByte(CP_UNIXCP, 0, text, -1, NULL, 0, NULL, NULL);
529 if (!(buffer = HeapAlloc( GetProcessHeap(), 0, count ))) return;
530 WideCharToMultiByte(CP_UNIXCP, 0, text, -1, buffer, count, NULL, NULL);
531
532 count = WideCharToMultiByte(CP_UTF8, 0, text, strlenW(text), NULL, 0, NULL, NULL);
533 if (!(utf8_buffer = HeapAlloc( GetProcessHeap(), 0, count )))
534 {
535 HeapFree( GetProcessHeap(), 0, buffer );
536 return;
537 }
538 WideCharToMultiByte(CP_UTF8, 0, text, strlenW(text), utf8_buffer, count, NULL, NULL);
539
540 wine_tsx11_lock();
541 if (XmbTextListToTextProperty( display, &buffer, 1, XStdICCTextStyle, &prop ) == Success)
542 {
543 XSetWMName( display, win, &prop );
544 XSetWMIconName( display, win, &prop );
545 XFree( prop.value );
546 }
547 /*
548 Implements a NET_WM UTF-8 title. It should be without a trailing \0,
549 according to the standard
550 ( http://www.pps.jussieu.fr/~jch/software/UTF8_STRING/UTF8_STRING.text ).
551 */
552 XChangeProperty( display, win, x11drv_atom(_NET_WM_NAME), x11drv_atom(UTF8_STRING),
553 8, PropModeReplace, (unsigned char *) utf8_buffer, count);
554 wine_tsx11_unlock();
555
556 HeapFree( GetProcessHeap(), 0, utf8_buffer );
557 HeapFree( GetProcessHeap(), 0, buffer );
558}
559
560
561/***********************************************************************
Alexandre Julliard370368a2008-09-08 15:42:24 +0200562 * set_win_format
Chris Robinsond9571c92007-09-15 13:02:32 -0700563 */
Alexandre Julliard370368a2008-09-08 15:42:24 +0200564static BOOL set_win_format( HWND hwnd, XID fbconfig_id )
Chris Robinsond9571c92007-09-15 13:02:32 -0700565{
566 struct x11drv_win_data *data;
Chris Robinson00633e32007-09-25 22:43:38 -0700567 XVisualInfo *vis;
Chris Robinson00633e32007-09-25 22:43:38 -0700568 int w, h;
Chris Robinsond9571c92007-09-15 13:02:32 -0700569
Alexandre Julliard026974f2008-01-24 10:20:51 +0100570 if (!(data = X11DRV_get_win_data(hwnd)) &&
571 !(data = X11DRV_create_win_data(hwnd))) return FALSE;
Chris Robinsond9571c92007-09-15 13:02:32 -0700572
Alexandre Julliarded371742008-05-28 17:02:07 +0200573 if (!(vis = visual_from_fbconfig_id(fbconfig_id))) return FALSE;
Chris Robinson00633e32007-09-25 22:43:38 -0700574
Alexandre Julliard42ad3452008-02-22 10:40:22 +0100575 if (data->whole_window)
Chris Robinson00633e32007-09-25 22:43:38 -0700576 {
Alexandre Julliard6e9dea82008-05-12 19:37:54 +0200577 Display *display = thread_display();
Alexandre Julliard42ad3452008-02-22 10:40:22 +0100578 Window client = data->client_window;
579
Alexandre Julliard30a133f2008-05-13 10:43:48 +0200580 if (vis->visualid != data->visualid)
Chris Robinson00633e32007-09-25 22:43:38 -0700581 {
Alexandre Julliard42ad3452008-02-22 10:40:22 +0100582 client = create_client_window( display, data, vis );
583 TRACE( "re-created client window %lx for %p fbconfig %lx\n", client, data->hwnd, fbconfig_id );
Chris Robinson00633e32007-09-25 22:43:38 -0700584 }
Alexandre Julliard42ad3452008-02-22 10:40:22 +0100585 wine_tsx11_lock();
586 XFree(vis);
Alexandre Julliard6e9dea82008-05-12 19:37:54 +0200587 XFlush( display );
Alexandre Julliard42ad3452008-02-22 10:40:22 +0100588 wine_tsx11_unlock();
589 if (client) goto done;
590 return FALSE;
Chris Robinson00633e32007-09-25 22:43:38 -0700591 }
592
593 w = data->client_rect.right - data->client_rect.left;
594 h = data->client_rect.bottom - data->client_rect.top;
595
596 if(w <= 0) w = 1;
597 if(h <= 0) h = 1;
598
Chris Robinson00633e32007-09-25 22:43:38 -0700599#ifdef SONAME_LIBXCOMPOSITE
600 if(usexcomposite)
601 {
602 XSetWindowAttributes attrib;
Alexandre Julliardb6059802008-05-12 19:14:11 +0200603 static Window dummy_parent;
Chris Robinson00633e32007-09-25 22:43:38 -0700604
Alexandre Julliard42ad3452008-02-22 10:40:22 +0100605 wine_tsx11_lock();
Alexandre Julliardb6059802008-05-12 19:14:11 +0200606 attrib.override_redirect = True;
607 if (!dummy_parent)
608 {
609 dummy_parent = XCreateWindow( gdi_display, root_window, -1, -1, 1, 1, 0, screen_depth,
610 InputOutput, visual, CWOverrideRedirect, &attrib );
611 XMapWindow( gdi_display, dummy_parent );
612 }
613 data->colormap = XCreateColormap(gdi_display, dummy_parent, vis->visual,
Alexandre Julliarde9307d02008-02-21 20:23:32 +0100614 (vis->class == PseudoColor ||
615 vis->class == GrayScale ||
616 vis->class == DirectColor) ?
617 AllocAll : AllocNone);
Alexandre Julliarde9307d02008-02-21 20:23:32 +0100618 attrib.colormap = data->colormap;
Chris Robinson00633e32007-09-25 22:43:38 -0700619 XInstallColormap(gdi_display, attrib.colormap);
620
Roderick Colenbranderf0307d92008-04-22 22:15:15 +0000621 if(data->gl_drawable) XDestroyWindow(gdi_display, data->gl_drawable);
Alexandre Julliardb6059802008-05-12 19:14:11 +0200622 data->gl_drawable = XCreateWindow(gdi_display, dummy_parent, -w, 0, w, h, 0,
Chris Robinson00633e32007-09-25 22:43:38 -0700623 vis->depth, InputOutput, vis->visual,
624 CWColormap | CWOverrideRedirect,
625 &attrib);
626 if(data->gl_drawable)
627 {
Alexandre Julliard6e9dea82008-05-12 19:37:54 +0200628 pXCompositeRedirectWindow(gdi_display, data->gl_drawable,
Chris Robinson00633e32007-09-25 22:43:38 -0700629 CompositeRedirectManual);
Alexandre Julliard6e9dea82008-05-12 19:37:54 +0200630 XMapWindow(gdi_display, data->gl_drawable);
Chris Robinson00633e32007-09-25 22:43:38 -0700631 }
Alexandre Julliard42ad3452008-02-22 10:40:22 +0100632 XFree(vis);
Alexandre Julliard6e9dea82008-05-12 19:37:54 +0200633 XFlush( gdi_display );
Alexandre Julliard42ad3452008-02-22 10:40:22 +0100634 wine_tsx11_unlock();
Chris Robinson00633e32007-09-25 22:43:38 -0700635 }
Chris Robinson37d835b2007-09-26 08:17:13 -0700636 else
Chris Robinson00633e32007-09-25 22:43:38 -0700637#endif
Chris Robinson37d835b2007-09-26 08:17:13 -0700638 {
639 WARN("XComposite is not available, using GLXPixmap hack\n");
640
Alexandre Julliard42ad3452008-02-22 10:40:22 +0100641 wine_tsx11_lock();
Roderick Colenbranderf0307d92008-04-22 22:15:15 +0000642
Alexandre Julliard6e9dea82008-05-12 19:37:54 +0200643 if(data->pixmap) XFreePixmap(gdi_display, data->pixmap);
644 data->pixmap = XCreatePixmap(gdi_display, root_window, w, h, vis->depth);
Chris Robinson37d835b2007-09-26 08:17:13 -0700645 if(!data->pixmap)
646 {
Chris Robinson37d835b2007-09-26 08:17:13 -0700647 XFree(vis);
648 wine_tsx11_unlock();
649 return FALSE;
650 }
651
Alexandre Julliard6e9dea82008-05-12 19:37:54 +0200652 if(data->gl_drawable) destroy_glxpixmap(gdi_display, data->gl_drawable);
653 data->gl_drawable = create_glxpixmap(gdi_display, vis, data->pixmap);
Chris Robinson37d835b2007-09-26 08:17:13 -0700654 if(!data->gl_drawable)
655 {
Alexandre Julliard6e9dea82008-05-12 19:37:54 +0200656 XFreePixmap(gdi_display, data->pixmap);
Chris Robinson37d835b2007-09-26 08:17:13 -0700657 data->pixmap = 0;
658 }
Chris Robinson00633e32007-09-25 22:43:38 -0700659 XFree(vis);
Alexandre Julliard6e9dea82008-05-12 19:37:54 +0200660 XFlush( gdi_display );
Chris Robinson00633e32007-09-25 22:43:38 -0700661 wine_tsx11_unlock();
Alexandre Julliard42ad3452008-02-22 10:40:22 +0100662 if (data->pixmap) SetPropA(hwnd, pixmap_prop, (HANDLE)data->pixmap);
Chris Robinson00633e32007-09-25 22:43:38 -0700663 }
664
Alexandre Julliard42ad3452008-02-22 10:40:22 +0100665 if (!data->gl_drawable) return FALSE;
Chris Robinson00633e32007-09-25 22:43:38 -0700666
667 TRACE("Created GL drawable 0x%lx, using FBConfigID 0x%lx\n",
668 data->gl_drawable, fbconfig_id);
Alexandre Julliard42ad3452008-02-22 10:40:22 +0100669 SetPropA(hwnd, gl_drawable_prop, (HANDLE)data->gl_drawable);
Chris Robinson00633e32007-09-25 22:43:38 -0700670
Alexandre Julliard42ad3452008-02-22 10:40:22 +0100671done:
Chris Robinsond9571c92007-09-15 13:02:32 -0700672 data->fbconfig_id = fbconfig_id;
673 SetPropA(hwnd, fbconfig_id_prop, (HANDLE)data->fbconfig_id);
Alexandre Julliard9727aa82008-04-21 20:32:22 +0200674 /* force DCE invalidation */
675 SetWindowPos( hwnd, 0, 0, 0, 0, 0,
676 SWP_NOACTIVATE | SWP_NOZORDER | SWP_NOSIZE | SWP_NOMOVE |
Alexandre Julliardfc8c21c2008-06-18 20:10:56 +0200677 SWP_NOREDRAW | SWP_DEFERERASE | SWP_NOSENDCHANGING | SWP_STATECHANGED);
Chris Robinsond9571c92007-09-15 13:02:32 -0700678 return TRUE;
679}
680
Alexandre Julliardbbfbe242008-01-23 12:28:01 +0100681/***********************************************************************
Alexandre Julliard8ee07d42008-02-21 12:29:36 +0100682 * sync_gl_drawable
Alexandre Julliardbbfbe242008-01-23 12:28:01 +0100683 */
Alexandre Julliard6e9dea82008-05-12 19:37:54 +0200684static void sync_gl_drawable(struct x11drv_win_data *data)
Chris Robinson00633e32007-09-25 22:43:38 -0700685{
686 int w = data->client_rect.right - data->client_rect.left;
687 int h = data->client_rect.bottom - data->client_rect.top;
Chris Robinson37d835b2007-09-26 08:17:13 -0700688 XVisualInfo *vis;
Chris Robinson37d835b2007-09-26 08:17:13 -0700689 Drawable glxp;
690 Pixmap pix;
Chris Robinson00633e32007-09-25 22:43:38 -0700691
Alexandre Julliardf13ef6b2008-02-22 16:30:10 +0100692 if (w <= 0) w = 1;
693 if (h <= 0) h = 1;
694
Chris Robinson00633e32007-09-25 22:43:38 -0700695 TRACE("Resizing GL drawable 0x%lx to %dx%d\n", data->gl_drawable, w, h);
696#ifdef SONAME_LIBXCOMPOSITE
697 if(usexcomposite)
698 {
699 wine_tsx11_lock();
Alexandre Julliard6e9dea82008-05-12 19:37:54 +0200700 XMoveResizeWindow(gdi_display, data->gl_drawable, -w, 0, w, h);
Chris Robinson00633e32007-09-25 22:43:38 -0700701 wine_tsx11_unlock();
702 return;
703 }
704#endif
Chris Robinson37d835b2007-09-26 08:17:13 -0700705
Alexandre Julliarded371742008-05-28 17:02:07 +0200706 if (!(vis = visual_from_fbconfig_id(data->fbconfig_id))) return;
707
Chris Robinson37d835b2007-09-26 08:17:13 -0700708 wine_tsx11_lock();
Alexandre Julliard6e9dea82008-05-12 19:37:54 +0200709 pix = XCreatePixmap(gdi_display, root_window, w, h, vis->depth);
Chris Robinson37d835b2007-09-26 08:17:13 -0700710 if(!pix)
711 {
712 ERR("Failed to create pixmap for offscreen rendering\n");
713 XFree(vis);
714 wine_tsx11_unlock();
715 return;
716 }
717
Alexandre Julliard6e9dea82008-05-12 19:37:54 +0200718 glxp = create_glxpixmap(gdi_display, vis, pix);
Chris Robinson37d835b2007-09-26 08:17:13 -0700719 if(!glxp)
720 {
721 ERR("Failed to create drawable for offscreen rendering\n");
Alexandre Julliard6e9dea82008-05-12 19:37:54 +0200722 XFreePixmap(gdi_display, pix);
Chris Robinson37d835b2007-09-26 08:17:13 -0700723 XFree(vis);
724 wine_tsx11_unlock();
725 return;
726 }
727
728 XFree(vis);
729
730 mark_drawable_dirty(data->gl_drawable, glxp);
731
Alexandre Julliard6e9dea82008-05-12 19:37:54 +0200732 XFreePixmap(gdi_display, data->pixmap);
733 destroy_glxpixmap(gdi_display, data->gl_drawable);
Alexandre Julliard9727aa82008-04-21 20:32:22 +0200734 TRACE( "Recreated GL drawable %lx to replace %lx\n", glxp, data->gl_drawable );
Chris Robinson37d835b2007-09-26 08:17:13 -0700735
736 data->pixmap = pix;
737 data->gl_drawable = glxp;
738
Alexandre Julliard6e9dea82008-05-12 19:37:54 +0200739 XFlush( gdi_display );
Chris Robinson37d835b2007-09-26 08:17:13 -0700740 wine_tsx11_unlock();
741
742 SetPropA(data->hwnd, gl_drawable_prop, (HANDLE)data->gl_drawable);
743 SetPropA(data->hwnd, pixmap_prop, (HANDLE)data->pixmap);
Chris Robinson00633e32007-09-25 22:43:38 -0700744}
745
Chris Robinsond9571c92007-09-15 13:02:32 -0700746
747/***********************************************************************
Alexandre Julliarddc4fe772001-06-04 21:55:17 +0000748 * get_window_changes
749 *
750 * fill the window changes structure
751 */
752static int get_window_changes( XWindowChanges *changes, const RECT *old, const RECT *new )
753{
754 int mask = 0;
755
756 if (old->right - old->left != new->right - new->left )
Alexandre Julliard9ae0fe52001-04-24 23:28:52 +0000757 {
Alexandre Julliard8ee07d42008-02-21 12:29:36 +0100758 if ((changes->width = new->right - new->left) <= 0) changes->width = 1;
Alexandre Julliarda4644f12009-05-05 15:36:25 +0200759 else if (changes->width > 65535) changes->width = 65535;
Alexandre Julliarddc4fe772001-06-04 21:55:17 +0000760 mask |= CWWidth;
Alexandre Julliard9ae0fe52001-04-24 23:28:52 +0000761 }
Alexandre Julliarddc4fe772001-06-04 21:55:17 +0000762 if (old->bottom - old->top != new->bottom - new->top)
763 {
Alexandre Julliard8ee07d42008-02-21 12:29:36 +0100764 if ((changes->height = new->bottom - new->top) <= 0) changes->height = 1;
Alexandre Julliarda4644f12009-05-05 15:36:25 +0200765 else if (changes->height > 65535) changes->height = 65535;
Alexandre Julliarddc4fe772001-06-04 21:55:17 +0000766 mask |= CWHeight;
767 }
768 if (old->left != new->left)
769 {
770 changes->x = new->left;
771 mask |= CWX;
772 }
773 if (old->top != new->top)
774 {
775 changes->y = new->top;
776 mask |= CWY;
777 }
778 return mask;
779}
780
781
782/***********************************************************************
783 * create_icon_window
784 */
Alexandre Julliardfc5ce142005-01-17 19:17:47 +0000785static Window create_icon_window( Display *display, struct x11drv_win_data *data )
Alexandre Julliarddc4fe772001-06-04 21:55:17 +0000786{
Alexandre Julliarddc4fe772001-06-04 21:55:17 +0000787 XSetWindowAttributes attr;
788
789 attr.event_mask = (ExposureMask | KeyPressMask | KeyReleaseMask | PointerMotionMask |
Alexandre Julliard9428f062002-06-14 00:08:40 +0000790 ButtonPressMask | ButtonReleaseMask | EnterWindowMask);
Alexandre Julliarddc4fe772001-06-04 21:55:17 +0000791 attr.bit_gravity = NorthWestGravity;
792 attr.backing_store = NotUseful/*WhenMapped*/;
Lionel Ulmer1fc39be2001-07-12 22:27:56 +0000793 attr.colormap = X11DRV_PALETTE_PaletteXColormap; /* Needed due to our visual */
Alexandre Julliarddc4fe772001-06-04 21:55:17 +0000794
Alexandre Julliard649637f2001-06-26 21:10:11 +0000795 wine_tsx11_lock();
796 data->icon_window = XCreateWindow( display, root_window, 0, 0,
797 GetSystemMetrics( SM_CXICON ),
798 GetSystemMetrics( SM_CYICON ),
799 0, screen_depth,
800 InputOutput, visual,
Lionel Ulmer1fc39be2001-07-12 22:27:56 +0000801 CWEventMask | CWBitGravity | CWBackingStore | CWColormap, &attr );
Alexandre Julliardfc5ce142005-01-17 19:17:47 +0000802 XSaveContext( display, data->icon_window, winContext, (char *)data->hwnd );
Alexandre Julliard731d77f2008-04-09 20:24:27 +0200803 XFlush( display ); /* make sure the window exists before we start painting to it */
Alexandre Julliard649637f2001-06-26 21:10:11 +0000804 wine_tsx11_unlock();
805
Alexandre Julliarddc4fe772001-06-04 21:55:17 +0000806 TRACE( "created %lx\n", data->icon_window );
Alexandre Julliardaf50ad62005-07-07 17:30:57 +0000807 SetPropA( data->hwnd, icon_window_prop, (HANDLE)data->icon_window );
Alexandre Julliarddc4fe772001-06-04 21:55:17 +0000808 return data->icon_window;
809}
810
811
812
813/***********************************************************************
814 * destroy_icon_window
815 */
Alexandre Julliardf777d702005-01-31 16:34:07 +0000816static void destroy_icon_window( Display *display, struct x11drv_win_data *data )
Alexandre Julliarddc4fe772001-06-04 21:55:17 +0000817{
818 if (!data->icon_window) return;
Alexandre Julliard704d0352001-07-12 02:49:31 +0000819 wine_tsx11_lock();
Alexandre Julliarddc4fe772001-06-04 21:55:17 +0000820 XDeleteContext( display, data->icon_window, winContext );
821 XDestroyWindow( display, data->icon_window );
822 data->icon_window = 0;
Alexandre Julliard704d0352001-07-12 02:49:31 +0000823 wine_tsx11_unlock();
Alexandre Julliardaf50ad62005-07-07 17:30:57 +0000824 RemovePropA( data->hwnd, icon_window_prop );
Alexandre Julliard9ae0fe52001-04-24 23:28:52 +0000825}
826
827
828/***********************************************************************
Alexandre Julliard42531202010-04-19 11:13:34 +0200829 * get_bitmap_argb
830 *
831 * Return the bitmap bits in ARGB format. Helper for setting icon hints.
832 */
833static unsigned long *get_bitmap_argb( HDC hdc, HBITMAP color, HBITMAP mask, unsigned int *size )
834{
835 BITMAP bm;
836 BITMAPINFO *info;
Alexandre Julliardf0644c62010-04-19 14:49:26 +0200837 unsigned int *ptr, *bits = NULL;
838 unsigned char *mask_bits = NULL;
839 int i, j, has_alpha = 0;
Alexandre Julliard42531202010-04-19 11:13:34 +0200840
841 if (!GetObjectW( color, sizeof(bm), &bm )) return NULL;
842 if (!(info = HeapAlloc( GetProcessHeap(), 0, FIELD_OFFSET( BITMAPINFO, bmiColors[256] )))) return NULL;
843 info->bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
844 info->bmiHeader.biWidth = bm.bmWidth;
845 info->bmiHeader.biHeight = -bm.bmHeight;
846 info->bmiHeader.biPlanes = 1;
847 info->bmiHeader.biBitCount = 32;
848 info->bmiHeader.biCompression = BI_RGB;
849 info->bmiHeader.biSizeImage = bm.bmWidth * bm.bmHeight * 4;
850 info->bmiHeader.biXPelsPerMeter = 0;
851 info->bmiHeader.biYPelsPerMeter = 0;
852 info->bmiHeader.biClrUsed = 0;
853 info->bmiHeader.biClrImportant = 0;
854 *size = bm.bmWidth * bm.bmHeight + 2;
855 if (!(bits = HeapAlloc( GetProcessHeap(), 0, *size * sizeof(long) ))) goto failed;
856 if (!GetDIBits( hdc, color, 0, bm.bmHeight, bits + 2, info, DIB_RGB_COLORS )) goto failed;
857
858 bits[0] = bm.bmWidth;
859 bits[1] = bm.bmHeight;
860
Alexandre Julliardf0644c62010-04-19 14:49:26 +0200861 for (i = 0; i < bm.bmWidth * bm.bmHeight; i++)
862 if ((has_alpha = (bits[i + 2] & 0xff000000) != 0)) break;
863
864 if (!has_alpha)
865 {
866 unsigned int width_bytes = (bm.bmWidth + 31) / 32 * 4;
867 /* generate alpha channel from the mask */
868 info->bmiHeader.biBitCount = 1;
869 info->bmiHeader.biSizeImage = width_bytes * bm.bmHeight;
870 if (!(mask_bits = HeapAlloc( GetProcessHeap(), 0, info->bmiHeader.biSizeImage ))) goto failed;
871 if (!GetDIBits( hdc, mask, 0, bm.bmHeight, mask_bits, info, DIB_RGB_COLORS )) goto failed;
872 ptr = bits + 2;
873 for (i = 0; i < bm.bmHeight; i++)
874 for (j = 0; j < bm.bmWidth; j++, ptr++)
Alexandre Julliard9ff982f2010-04-22 14:16:44 +0200875 if (!((mask_bits[i * width_bytes + j / 8] << (j % 8)) & 0x80)) *ptr |= 0xff000000;
Alexandre Julliardf84f9392010-04-20 13:55:11 +0200876 HeapFree( GetProcessHeap(), 0, mask_bits );
Alexandre Julliardf0644c62010-04-19 14:49:26 +0200877 }
Alexandre Julliardf84f9392010-04-20 13:55:11 +0200878 HeapFree( GetProcessHeap(), 0, info );
Alexandre Julliardf0644c62010-04-19 14:49:26 +0200879
Alexandre Julliard42531202010-04-19 11:13:34 +0200880 /* convert to array of longs */
881 if (bits && sizeof(long) > sizeof(int))
882 for (i = *size - 1; i >= 0; i--) ((unsigned long *)bits)[i] = bits[i];
883
884 return (unsigned long *)bits;
885
886failed:
887 HeapFree( GetProcessHeap(), 0, info );
888 HeapFree( GetProcessHeap(), 0, bits );
Alexandre Julliardf0644c62010-04-19 14:49:26 +0200889 HeapFree( GetProcessHeap(), 0, mask_bits );
Alexandre Julliard42531202010-04-19 11:13:34 +0200890 return NULL;
891}
892
893
894/***********************************************************************
Alexandre Julliard9ae0fe52001-04-24 23:28:52 +0000895 * set_icon_hints
896 *
897 * Set the icon wm hints
898 */
Alexandre Julliarda551dfe2010-04-19 17:51:44 +0200899static void set_icon_hints( Display *display, struct x11drv_win_data *data,
900 HICON icon_big, HICON icon_small )
Alexandre Julliard9ae0fe52001-04-24 23:28:52 +0000901{
Alexandre Julliardbde89572007-08-16 23:27:37 +0200902 XWMHints *hints = data->wm_hints;
903
Alexandre Julliarda551dfe2010-04-19 17:51:44 +0200904 if (!icon_big)
905 {
906 icon_big = (HICON)SendMessageW( data->hwnd, WM_GETICON, ICON_BIG, 0 );
907 if (!icon_big) icon_big = (HICON)GetClassLongPtrW( data->hwnd, GCLP_HICON );
908 }
909 if (!icon_small)
910 {
911 icon_small = (HICON)SendMessageW( data->hwnd, WM_GETICON, ICON_SMALL, 0 );
912 if (!icon_small) icon_small = (HICON)GetClassLongPtrW( data->hwnd, GCLP_HICONSM );
913 }
914
Alexandre Julliard9ae0fe52001-04-24 23:28:52 +0000915 if (data->hWMIconBitmap) DeleteObject( data->hWMIconBitmap );
916 if (data->hWMIconMask) DeleteObject( data->hWMIconMask);
Alexandre Julliard883cff42001-06-12 04:02:10 +0000917 data->hWMIconBitmap = 0;
918 data->hWMIconMask = 0;
Alexandre Julliard9ae0fe52001-04-24 23:28:52 +0000919
Alexandre Julliarda551dfe2010-04-19 17:51:44 +0200920 if (!icon_big)
Alexandre Julliard883cff42001-06-12 04:02:10 +0000921 {
Alexandre Julliardfc5ce142005-01-17 19:17:47 +0000922 if (!data->icon_window) create_icon_window( display, data );
Alexandre Julliarddc4fe772001-06-04 21:55:17 +0000923 hints->icon_window = data->icon_window;
924 hints->flags = (hints->flags & ~(IconPixmapHint | IconMaskHint)) | IconWindowHint;
Alexandre Julliard9ae0fe52001-04-24 23:28:52 +0000925 }
926 else
927 {
928 HBITMAP hbmOrig;
929 RECT rcMask;
Alexandre Julliardea1d71c2010-04-16 16:23:33 +0200930 BITMAP bm;
Alexandre Julliard0d84ccb2010-05-20 17:37:28 +0200931 ICONINFO ii, ii_small;
Alexandre Julliard9ae0fe52001-04-24 23:28:52 +0000932 HDC hDC;
Alexandre Julliard42531202010-04-19 11:13:34 +0200933 unsigned int size;
934 unsigned long *bits;
Alexandre Julliard9ae0fe52001-04-24 23:28:52 +0000935
Alexandre Julliard0d84ccb2010-05-20 17:37:28 +0200936 if (!GetIconInfo(icon_big, &ii)) return;
Alexandre Julliard9ae0fe52001-04-24 23:28:52 +0000937
Alexandre Julliardea1d71c2010-04-16 16:23:33 +0200938 GetObjectW(ii.hbmMask, sizeof(bm), &bm);
Alexandre Julliard9ae0fe52001-04-24 23:28:52 +0000939 rcMask.top = 0;
940 rcMask.left = 0;
Alexandre Julliardea1d71c2010-04-16 16:23:33 +0200941 rcMask.right = bm.bmWidth;
942 rcMask.bottom = bm.bmHeight;
Alexandre Julliard9ae0fe52001-04-24 23:28:52 +0000943
944 hDC = CreateCompatibleDC(0);
Alexandre Julliarda551dfe2010-04-19 17:51:44 +0200945 bits = get_bitmap_argb( hDC, ii.hbmColor, ii.hbmMask, &size );
Alexandre Julliard0d84ccb2010-05-20 17:37:28 +0200946 if (bits && GetIconInfo( icon_small, &ii_small ))
Alexandre Julliarda551dfe2010-04-19 17:51:44 +0200947 {
948 unsigned int size_small;
949 unsigned long *bits_small, *new;
950
Alexandre Julliard0d84ccb2010-05-20 17:37:28 +0200951 if ((bits_small = get_bitmap_argb( hDC, ii_small.hbmColor, ii_small.hbmMask, &size_small )) &&
Alexandre Julliard09dc6012010-04-22 14:47:57 +0200952 (bits_small[0] != bits[0] || bits_small[1] != bits[1])) /* size must be different */
Alexandre Julliarda551dfe2010-04-19 17:51:44 +0200953 {
954 if ((new = HeapReAlloc( GetProcessHeap(), 0, bits,
955 (size + size_small) * sizeof(unsigned long) )))
956 {
957 bits = new;
958 memcpy( bits + size, bits_small, size_small * sizeof(unsigned long) );
959 size += size_small;
960 }
Alexandre Julliarda551dfe2010-04-19 17:51:44 +0200961 }
Alexandre Julliard09dc6012010-04-22 14:47:57 +0200962 HeapFree( GetProcessHeap(), 0, bits_small );
Alexandre Julliard0d84ccb2010-05-20 17:37:28 +0200963 DeleteObject( ii_small.hbmColor );
964 DeleteObject( ii_small.hbmMask );
Alexandre Julliarda551dfe2010-04-19 17:51:44 +0200965 }
966 wine_tsx11_lock();
967 if (bits)
968 XChangeProperty( display, data->whole_window, x11drv_atom(_NET_WM_ICON),
969 XA_CARDINAL, 32, PropModeReplace, (unsigned char *)bits, size );
970 else
971 XDeleteProperty( display, data->whole_window, x11drv_atom(_NET_WM_ICON) );
972 wine_tsx11_unlock();
973 HeapFree( GetProcessHeap(), 0, bits );
974
Alexandre Julliard9ff982f2010-04-22 14:16:44 +0200975 hbmOrig = SelectObject(hDC, ii.hbmMask);
976 InvertRect(hDC, &rcMask);
977 SelectObject(hDC, ii.hbmColor); /* force the color bitmap to x11drv mode too */
978 SelectObject(hDC, hbmOrig);
979
980 data->hWMIconBitmap = ii.hbmColor;
981 data->hWMIconMask = ii.hbmMask;
982
983 hints->icon_pixmap = X11DRV_get_pixmap(data->hWMIconBitmap);
984 hints->icon_mask = X11DRV_get_pixmap(data->hWMIconMask);
985 destroy_icon_window( display, data );
986 hints->flags = (hints->flags & ~IconWindowHint) | IconPixmapHint | IconMaskHint;
987
Alexandre Julliarda551dfe2010-04-19 17:51:44 +0200988 DeleteDC(hDC);
Alexandre Julliard9ae0fe52001-04-24 23:28:52 +0000989 }
990}
991
992
993/***********************************************************************
Alexandre Julliarddc4fe772001-06-04 21:55:17 +0000994 * set_size_hints
Alexandre Julliard9ae0fe52001-04-24 23:28:52 +0000995 *
Alexandre Julliarddc4fe772001-06-04 21:55:17 +0000996 * set the window size hints
Alexandre Julliard9ae0fe52001-04-24 23:28:52 +0000997 */
Alexandre Julliardfc5ce142005-01-17 19:17:47 +0000998static void set_size_hints( Display *display, struct x11drv_win_data *data, DWORD style )
Alexandre Julliard9ae0fe52001-04-24 23:28:52 +0000999{
Alexandre Julliarddc4fe772001-06-04 21:55:17 +00001000 XSizeHints* size_hints;
Alexandre Julliarddc4fe772001-06-04 21:55:17 +00001001
Alexandre Julliardcf9d3e32008-04-04 11:28:30 +02001002 if (!(size_hints = XAllocSizeHints())) return;
Alexandre Julliardba1517f2006-03-27 22:16:04 +02001003
Alexandre Julliard6ba06fa2008-04-23 15:33:29 +02001004 size_hints->win_gravity = StaticGravity;
1005 size_hints->flags |= PWinGravity;
1006
Alexandre Julliardcf9d3e32008-04-04 11:28:30 +02001007 /* don't update size hints if window is not in normal state */
1008 if (!(style & (WS_MINIMIZE | WS_MAXIMIZE)))
1009 {
Alexandre Julliardba1517f2006-03-27 22:16:04 +02001010 if (data->hwnd != GetDesktopWindow()) /* don't force position of desktop */
1011 {
Alexandre Julliardba1517f2006-03-27 22:16:04 +02001012 size_hints->x = data->whole_rect.left;
1013 size_hints->y = data->whole_rect.top;
Alexandre Julliard6ba06fa2008-04-23 15:33:29 +02001014 size_hints->flags |= PPosition;
Alexandre Julliardba1517f2006-03-27 22:16:04 +02001015 }
Alexandre Julliarddc4fe772001-06-04 21:55:17 +00001016
Alexandre Julliard4d14adf2008-04-04 11:25:48 +02001017 if (!is_window_resizable( data, style ))
Alexandre Julliarddc4fe772001-06-04 21:55:17 +00001018 {
Alexandre Julliard4d14adf2008-04-04 11:25:48 +02001019 size_hints->max_width = data->whole_rect.right - data->whole_rect.left;
1020 size_hints->max_height = data->whole_rect.bottom - data->whole_rect.top;
Alexandre Julliard81c4b412010-05-28 12:13:01 +02001021 if (size_hints->max_width <= 0 ||size_hints->max_height <= 0)
1022 size_hints->max_width = size_hints->max_height = 1;
Alexandre Julliard4d14adf2008-04-04 11:25:48 +02001023 size_hints->min_width = size_hints->max_width;
1024 size_hints->min_height = size_hints->max_height;
1025 size_hints->flags |= PMinSize | PMaxSize;
Alexandre Julliarddc4fe772001-06-04 21:55:17 +00001026 }
Alexandre Julliarddc4fe772001-06-04 21:55:17 +00001027 }
Alexandre Julliardcf9d3e32008-04-04 11:28:30 +02001028 XSetWMNormalHints( display, data->whole_window, size_hints );
1029 XFree( size_hints );
Alexandre Julliarddc4fe772001-06-04 21:55:17 +00001030}
1031
1032
1033/***********************************************************************
Alexandre Julliardc7dbffc2005-07-01 16:16:00 +00001034 * get_process_name
1035 *
1036 * get the name of the current process for setting class hints
1037 */
1038static char *get_process_name(void)
1039{
1040 static char *name;
1041
1042 if (!name)
1043 {
1044 WCHAR module[MAX_PATH];
1045 DWORD len = GetModuleFileNameW( 0, module, MAX_PATH );
1046 if (len && len < MAX_PATH)
1047 {
1048 char *ptr;
1049 WCHAR *p, *appname = module;
1050
1051 if ((p = strrchrW( appname, '/' ))) appname = p + 1;
1052 if ((p = strrchrW( appname, '\\' ))) appname = p + 1;
1053 len = WideCharToMultiByte( CP_UNIXCP, 0, appname, -1, NULL, 0, NULL, NULL );
1054 if ((ptr = HeapAlloc( GetProcessHeap(), 0, len )))
1055 {
1056 WideCharToMultiByte( CP_UNIXCP, 0, appname, -1, ptr, len, NULL, NULL );
1057 name = ptr;
1058 }
1059 }
1060 }
1061 return name;
1062}
1063
1064
1065/***********************************************************************
Alexandre Julliard7d9739e2007-08-20 14:04:36 +02001066 * set_initial_wm_hints
Alexandre Julliarddc4fe772001-06-04 21:55:17 +00001067 *
Alexandre Julliard7d9739e2007-08-20 14:04:36 +02001068 * Set the window manager hints that don't change over the lifetime of a window.
Alexandre Julliarddc4fe772001-06-04 21:55:17 +00001069 */
Alexandre Julliard7d9739e2007-08-20 14:04:36 +02001070static void set_initial_wm_hints( Display *display, struct x11drv_win_data *data )
Alexandre Julliarddc4fe772001-06-04 21:55:17 +00001071{
Alexandre Julliard3bfa90e2008-04-07 11:41:54 +02001072 long i;
Alexandre Julliard7d9739e2007-08-20 14:04:36 +02001073 Atom protocols[3];
Kusanagi Kouichi10789142010-02-20 17:57:07 +09001074 Atom dndVersion = WINE_XDND_VERSION;
Alexandre Julliard7d9739e2007-08-20 14:04:36 +02001075 XClassHint *class_hints;
Alexandre Julliardc7dbffc2005-07-01 16:16:00 +00001076 char *process_name = get_process_name();
Alexandre Julliardfc5ce142005-01-17 19:17:47 +00001077
Alexandre Julliarddc4fe772001-06-04 21:55:17 +00001078 wine_tsx11_lock();
1079
1080 /* wm protocols */
1081 i = 0;
Alexandre Julliardd09c3282003-11-20 04:24:18 +00001082 protocols[i++] = x11drv_atom(WM_DELETE_WINDOW);
1083 protocols[i++] = x11drv_atom(_NET_WM_PING);
1084 if (use_take_focus) protocols[i++] = x11drv_atom(WM_TAKE_FOCUS);
1085 XChangeProperty( display, data->whole_window, x11drv_atom(WM_PROTOCOLS),
Hans Leidekkerac147fe2005-03-22 21:17:34 +00001086 XA_ATOM, 32, PropModeReplace, (unsigned char *)protocols, i );
Alexandre Julliarddc4fe772001-06-04 21:55:17 +00001087
1088 /* class hints */
1089 if ((class_hints = XAllocClassHint()))
1090 {
Andrew Talbot55e20a72006-06-26 20:56:16 +01001091 static char wine[] = "Wine";
1092
Alexandre Julliardc7dbffc2005-07-01 16:16:00 +00001093 class_hints->res_name = process_name;
Andrew Talbot55e20a72006-06-26 20:56:16 +01001094 class_hints->res_class = wine;
Alexandre Julliarddc4fe772001-06-04 21:55:17 +00001095 XSetClassHint( display, data->whole_window, class_hints );
1096 XFree( class_hints );
1097 }
1098
Mike Hearn34dd4552003-05-04 02:27:20 +00001099 /* set the WM_CLIENT_MACHINE and WM_LOCALE_NAME properties */
1100 XSetWMProperties(display, data->whole_window, NULL, NULL, NULL, 0, NULL, NULL, NULL);
1101 /* set the pid. together, these properties are needed so the window manager can kill us if we freeze */
1102 i = getpid();
Alexandre Julliardd09c3282003-11-20 04:24:18 +00001103 XChangeProperty(display, data->whole_window, x11drv_atom(_NET_WM_PID),
Hans Leidekkerac147fe2005-03-22 21:17:34 +00001104 XA_CARDINAL, 32, PropModeReplace, (unsigned char *)&i, 1);
Ove Kaaven77e7fd72002-01-21 18:41:27 +00001105
Alexandre Julliard7d9739e2007-08-20 14:04:36 +02001106 XChangeProperty( display, data->whole_window, x11drv_atom(XdndAware),
1107 XA_ATOM, 32, PropModeReplace, (unsigned char*)&dndVersion, 1 );
1108
Alexandre Julliarddc07b6f2008-01-22 10:17:52 +01001109 data->wm_hints = XAllocWMHints();
Alexandre Julliard7d9739e2007-08-20 14:04:36 +02001110 wine_tsx11_unlock();
Alexandre Julliard6a23bd82008-01-18 14:34:57 +01001111
1112 if (data->wm_hints)
1113 {
1114 data->wm_hints->flags = 0;
Alexandre Julliarda551dfe2010-04-19 17:51:44 +02001115 set_icon_hints( display, data, 0, 0 );
Alexandre Julliard6a23bd82008-01-18 14:34:57 +01001116 }
Alexandre Julliard7d9739e2007-08-20 14:04:36 +02001117}
1118
1119
1120/***********************************************************************
Alexandre Julliard7b3a00c2010-02-23 12:33:01 +01001121 * get_owner_whole_window
1122 *
1123 * Retrieve an owner's window, creating it if necessary.
1124 */
Alexandre Julliardb6ef8a52010-03-20 20:16:42 +01001125static Window get_owner_whole_window( HWND owner, BOOL force_managed )
Alexandre Julliard7b3a00c2010-02-23 12:33:01 +01001126{
1127 struct x11drv_win_data *data;
1128
1129 if (!owner) return 0;
1130
1131 if (!(data = X11DRV_get_win_data( owner )))
1132 {
Alexandre Julliard9cd1ce22010-03-01 17:06:19 +01001133 if (GetWindowThreadProcessId( owner, NULL ) != GetCurrentThreadId() ||
1134 !(data = X11DRV_create_win_data( owner )))
Alexandre Julliard7b3a00c2010-02-23 12:33:01 +01001135 return (Window)GetPropA( owner, whole_window_prop );
1136 }
Alexandre Julliardb6ef8a52010-03-20 20:16:42 +01001137 else if (!data->managed && force_managed) /* make it managed */
Alexandre Julliard913cab12010-02-23 12:35:10 +01001138 {
1139 SetWindowPos( owner, 0, 0, 0, 0, 0,
1140 SWP_NOACTIVATE | SWP_NOZORDER | SWP_NOSIZE | SWP_NOMOVE |
1141 SWP_NOREDRAW | SWP_DEFERERASE | SWP_NOSENDCHANGING | SWP_STATECHANGED );
1142 }
Alexandre Julliard7b3a00c2010-02-23 12:33:01 +01001143 return data->whole_window;
1144}
1145
1146
1147/***********************************************************************
Alexandre Julliard855308f2008-04-23 15:32:58 +02001148 * set_wm_hints
Alexandre Julliard7d9739e2007-08-20 14:04:36 +02001149 *
1150 * Set the window manager hints for a newly-created window
1151 */
Alexandre Julliard855308f2008-04-23 15:32:58 +02001152static void set_wm_hints( Display *display, struct x11drv_win_data *data )
Alexandre Julliard7d9739e2007-08-20 14:04:36 +02001153{
Alexandre Julliard7b3a00c2010-02-23 12:33:01 +01001154 Window group_leader = data->whole_window;
1155 Window owner_win = 0;
Alexandre Julliard7d9739e2007-08-20 14:04:36 +02001156 Atom window_type;
1157 MwmHints mwm_hints;
Alexandre Julliard18f4fb92008-04-14 13:27:38 +02001158 DWORD style, ex_style;
1159 HWND owner;
Alexandre Julliard7d9739e2007-08-20 14:04:36 +02001160
1161 if (data->hwnd == GetDesktopWindow())
1162 {
Alexandre Julliard7d9739e2007-08-20 14:04:36 +02001163 /* force some styles for the desktop to get the correct decorations */
Alexandre Julliard18f4fb92008-04-14 13:27:38 +02001164 style = WS_POPUP | WS_VISIBLE | WS_CAPTION | WS_SYSMENU | WS_MINIMIZEBOX;
1165 ex_style = WS_EX_APPWINDOW;
Alexandre Julliard7d9739e2007-08-20 14:04:36 +02001166 owner = 0;
1167 }
Alexandre Julliard18f4fb92008-04-14 13:27:38 +02001168 else
1169 {
1170 style = GetWindowLongW( data->hwnd, GWL_STYLE );
1171 ex_style = GetWindowLongW( data->hwnd, GWL_EXSTYLE );
Alexandre Julliard8a5f5782008-05-01 17:44:56 +02001172 owner = get_window_owner( data->hwnd );
Alexandre Julliardb6ef8a52010-03-20 20:16:42 +01001173 if ((owner_win = get_owner_whole_window( owner, data->managed ))) group_leader = owner_win;
Alexandre Julliard18f4fb92008-04-14 13:27:38 +02001174 }
Alexandre Julliard7d9739e2007-08-20 14:04:36 +02001175
Alexandre Julliard7d9739e2007-08-20 14:04:36 +02001176 wine_tsx11_lock();
1177
Alexandre Julliard7b3a00c2010-02-23 12:33:01 +01001178 if (owner_win) XSetTransientForHint( display, data->whole_window, owner_win );
1179
Alexandre Julliard7d9739e2007-08-20 14:04:36 +02001180 /* size hints */
1181 set_size_hints( display, data, style );
1182
Nickolay V. Shmyrev1a1b9022006-10-11 19:32:22 +04001183 /* set the WM_WINDOW_TYPE */
Dmitry Timoshkov751a71a2008-04-07 13:37:44 +09001184 if (style & WS_THICKFRAME) window_type = x11drv_atom(_NET_WM_WINDOW_TYPE_NORMAL);
Alexandre Julliard9bf9c0b2008-04-14 13:27:19 +02001185 else if (ex_style & WS_EX_APPWINDOW) window_type = x11drv_atom(_NET_WM_WINDOW_TYPE_NORMAL);
Alexandre Julliard8b84d642010-05-28 12:12:32 +02001186 else if (style & WS_MINIMIZEBOX) window_type = x11drv_atom(_NET_WM_WINDOW_TYPE_NORMAL);
Nickolay V. Shmyrev1a1b9022006-10-11 19:32:22 +04001187 else if (style & WS_DLGFRAME) window_type = x11drv_atom(_NET_WM_WINDOW_TYPE_DIALOG);
1188 else if (ex_style & WS_EX_DLGMODALFRAME) window_type = x11drv_atom(_NET_WM_WINDOW_TYPE_DIALOG);
Alexandre Julliard0bbadeb2008-04-21 20:33:18 +02001189 else if ((style & WS_POPUP) && owner) window_type = x11drv_atom(_NET_WM_WINDOW_TYPE_DIALOG);
Dmitry Timoshkov1bf824e2008-04-07 22:17:47 +09001190#if 0 /* many window managers don't handle utility windows very well */
Dmitry Timoshkov751a71a2008-04-07 13:37:44 +09001191 else if (ex_style & WS_EX_TOOLWINDOW) window_type = x11drv_atom(_NET_WM_WINDOW_TYPE_UTILITY);
Dmitry Timoshkov1bf824e2008-04-07 22:17:47 +09001192#endif
Alexandre Julliard9bf9c0b2008-04-14 13:27:19 +02001193 else window_type = x11drv_atom(_NET_WM_WINDOW_TYPE_NORMAL);
Nickolay V. Shmyrev1a1b9022006-10-11 19:32:22 +04001194
1195 XChangeProperty(display, data->whole_window, x11drv_atom(_NET_WM_WINDOW_TYPE),
1196 XA_ATOM, 32, PropModeReplace, (unsigned char*)&window_type, 1);
Mike Hearn27d972f2003-12-04 21:54:13 +00001197
Alexandre Julliardd09c3282003-11-20 04:24:18 +00001198 mwm_hints.flags = MWM_HINTS_FUNCTIONS | MWM_HINTS_DECORATIONS;
Dmitry Timoshkov15c0bcb2008-04-16 16:50:29 +09001199 mwm_hints.decorations = get_mwm_decorations( data, style, ex_style );
Dmitry Timoshkovac387bb2006-10-05 23:16:36 +09001200 mwm_hints.functions = MWM_FUNC_MOVE;
Alexandre Julliard4d14adf2008-04-04 11:25:48 +02001201 if (is_window_resizable( data, style )) mwm_hints.functions |= MWM_FUNC_RESIZE;
Dmitry Timoshkove35e75b2010-04-07 15:41:01 +09001202 if (!(style & WS_DISABLED))
1203 {
1204 if (style & WS_MINIMIZEBOX) mwm_hints.functions |= MWM_FUNC_MINIMIZE;
1205 if (style & WS_MAXIMIZEBOX) mwm_hints.functions |= MWM_FUNC_MAXIMIZE;
1206 if (style & WS_SYSMENU) mwm_hints.functions |= MWM_FUNC_CLOSE;
1207 }
Alexandre Julliardd09c3282003-11-20 04:24:18 +00001208
1209 XChangeProperty( display, data->whole_window, x11drv_atom(_MOTIF_WM_HINTS),
1210 x11drv_atom(_MOTIF_WM_HINTS), 32, PropModeReplace,
Hans Leidekkerac147fe2005-03-22 21:17:34 +00001211 (unsigned char*)&mwm_hints, sizeof(mwm_hints)/sizeof(long) );
Alexandre Julliarddc4fe772001-06-04 21:55:17 +00001212
Alexandre Julliard704d0352001-07-12 02:49:31 +00001213 /* wm hints */
Alexandre Julliardbde89572007-08-16 23:27:37 +02001214 if (data->wm_hints)
Alexandre Julliard704d0352001-07-12 02:49:31 +00001215 {
Alexandre Julliard6a23bd82008-01-18 14:34:57 +01001216 data->wm_hints->flags |= InputHint | StateHint | WindowGroupHint;
Alexandre Julliarde3720c22009-08-13 18:18:22 +02001217 data->wm_hints->input = !use_take_focus && !(style & WS_DISABLED);
Alexandre Julliardbde89572007-08-16 23:27:37 +02001218 data->wm_hints->initial_state = (style & WS_MINIMIZE) ? IconicState : NormalState;
1219 data->wm_hints->window_group = group_leader;
Alexandre Julliardbde89572007-08-16 23:27:37 +02001220 XSetWMHints( display, data->whole_window, data->wm_hints );
Alexandre Julliard704d0352001-07-12 02:49:31 +00001221 }
Alexandre Julliard6a23bd82008-01-18 14:34:57 +01001222
1223 wine_tsx11_unlock();
Alexandre Julliarddc4fe772001-06-04 21:55:17 +00001224}
1225
1226
1227/***********************************************************************
Alexandre Julliard855308f2008-04-23 15:32:58 +02001228 * update_net_wm_states
1229 */
1230void update_net_wm_states( Display *display, struct x11drv_win_data *data )
1231{
1232 static const unsigned int state_atoms[NB_NET_WM_STATES] =
1233 {
1234 XATOM__NET_WM_STATE_FULLSCREEN,
1235 XATOM__NET_WM_STATE_ABOVE,
1236 XATOM__NET_WM_STATE_MAXIMIZED_VERT,
1237 XATOM__NET_WM_STATE_SKIP_PAGER,
1238 XATOM__NET_WM_STATE_SKIP_TASKBAR
1239 };
1240
1241 DWORD i, style, ex_style, new_state = 0;
1242
1243 if (!data->managed) return;
1244 if (data->whole_window == root_window) return;
1245
1246 style = GetWindowLongW( data->hwnd, GWL_STYLE );
1247 if (data->whole_rect.left <= 0 && data->whole_rect.right >= screen_width &&
1248 data->whole_rect.top <= 0 && data->whole_rect.bottom >= screen_height)
1249 {
1250 if ((style & WS_MAXIMIZE) && (style & WS_CAPTION) == WS_CAPTION)
1251 new_state |= (1 << NET_WM_STATE_MAXIMIZED);
1252 else if (!(style & WS_MINIMIZE))
1253 new_state |= (1 << NET_WM_STATE_FULLSCREEN);
1254 }
1255 else if (style & WS_MAXIMIZE)
1256 new_state |= (1 << NET_WM_STATE_MAXIMIZED);
1257
1258 ex_style = GetWindowLongW( data->hwnd, GWL_EXSTYLE );
1259 if (ex_style & WS_EX_TOPMOST)
1260 new_state |= (1 << NET_WM_STATE_ABOVE);
1261 if (ex_style & WS_EX_TOOLWINDOW)
1262 new_state |= (1 << NET_WM_STATE_SKIP_TASKBAR) | (1 << NET_WM_STATE_SKIP_PAGER);
Alexandre Julliard8a5f5782008-05-01 17:44:56 +02001263 if (!(ex_style & WS_EX_APPWINDOW) && get_window_owner( data->hwnd ))
Alexandre Julliard855308f2008-04-23 15:32:58 +02001264 new_state |= (1 << NET_WM_STATE_SKIP_TASKBAR);
1265
1266 if (!data->mapped) /* set the _NET_WM_STATE atom directly */
1267 {
1268 Atom atoms[NB_NET_WM_STATES+1];
1269 DWORD count;
1270
1271 for (i = count = 0; i < NB_NET_WM_STATES; i++)
1272 {
1273 if (!(new_state & (1 << i))) continue;
1274 TRACE( "setting wm state %u for unmapped window %p/%lx\n",
1275 i, data->hwnd, data->whole_window );
1276 atoms[count++] = X11DRV_Atoms[state_atoms[i] - FIRST_XATOM];
1277 if (state_atoms[i] == XATOM__NET_WM_STATE_MAXIMIZED_VERT)
1278 atoms[count++] = x11drv_atom(_NET_WM_STATE_MAXIMIZED_HORZ);
1279 }
1280 wine_tsx11_lock();
1281 XChangeProperty( display, data->whole_window, x11drv_atom(_NET_WM_STATE), XA_ATOM,
1282 32, PropModeReplace, (unsigned char *)atoms, count );
1283 wine_tsx11_unlock();
1284 }
1285 else /* ask the window manager to do it for us */
1286 {
1287 XEvent xev;
1288
1289 xev.xclient.type = ClientMessage;
1290 xev.xclient.window = data->whole_window;
1291 xev.xclient.message_type = x11drv_atom(_NET_WM_STATE);
1292 xev.xclient.serial = 0;
1293 xev.xclient.display = display;
1294 xev.xclient.send_event = True;
1295 xev.xclient.format = 32;
1296 xev.xclient.data.l[3] = 1;
1297
1298 for (i = 0; i < NB_NET_WM_STATES; i++)
1299 {
1300 if (!((data->net_wm_state ^ new_state) & (1 << i))) continue; /* unchanged */
1301
1302 TRACE( "setting wm state %u for window %p/%lx to %u prev %u\n",
1303 i, data->hwnd, data->whole_window,
1304 (new_state & (1 << i)) != 0, (data->net_wm_state & (1 << i)) != 0 );
1305
1306 xev.xclient.data.l[0] = (new_state & (1 << i)) ? _NET_WM_STATE_ADD : _NET_WM_STATE_REMOVE;
1307 xev.xclient.data.l[1] = X11DRV_Atoms[state_atoms[i] - FIRST_XATOM];
1308 xev.xclient.data.l[2] = ((state_atoms[i] == XATOM__NET_WM_STATE_MAXIMIZED_VERT) ?
1309 x11drv_atom(_NET_WM_STATE_MAXIMIZED_HORZ) : 0);
1310 wine_tsx11_lock();
1311 XSendEvent( display, root_window, False,
1312 SubstructureRedirectMask | SubstructureNotifyMask, &xev );
1313 wine_tsx11_unlock();
1314 }
1315 }
1316 data->net_wm_state = new_state;
1317}
1318
1319
1320/***********************************************************************
1321 * set_xembed_flags
1322 */
1323static void set_xembed_flags( Display *display, struct x11drv_win_data *data, unsigned long flags )
1324{
1325 unsigned long info[2];
1326
1327 info[0] = 0; /* protocol version */
1328 info[1] = flags;
1329 wine_tsx11_lock();
1330 XChangeProperty( display, data->whole_window, x11drv_atom(_XEMBED_INFO),
1331 x11drv_atom(_XEMBED_INFO), 32, PropModeReplace, (unsigned char*)info, 2 );
1332 wine_tsx11_unlock();
1333}
1334
1335
1336/***********************************************************************
1337 * map_window
1338 */
1339static void map_window( Display *display, struct x11drv_win_data *data, DWORD new_style )
1340{
1341 TRACE( "win %p/%lx\n", data->hwnd, data->whole_window );
1342
Damjan Jovanovic3613b152009-01-06 20:59:07 +02001343 remove_startup_notification( display, data->whole_window );
1344
Alexandre Julliard855308f2008-04-23 15:32:58 +02001345 wait_for_withdrawn_state( display, data, TRUE );
1346
1347 if (!data->embedded)
1348 {
1349 update_net_wm_states( display, data );
1350 sync_window_style( display, data );
1351 wine_tsx11_lock();
1352 XMapWindow( display, data->whole_window );
1353 wine_tsx11_unlock();
1354 }
1355 else set_xembed_flags( display, data, XEMBED_MAPPED );
1356
1357 data->mapped = TRUE;
1358 data->iconic = (new_style & WS_MINIMIZE) != 0;
1359}
1360
1361
1362/***********************************************************************
1363 * unmap_window
1364 */
1365static void unmap_window( Display *display, struct x11drv_win_data *data )
1366{
1367 TRACE( "win %p/%lx\n", data->hwnd, data->whole_window );
1368
1369 if (!data->embedded)
1370 {
1371 wait_for_withdrawn_state( display, data, FALSE );
1372 wine_tsx11_lock();
1373 if (data->managed) XWithdrawWindow( display, data->whole_window, DefaultScreen(display) );
1374 else XUnmapWindow( display, data->whole_window );
1375 wine_tsx11_unlock();
1376 }
1377 else set_xembed_flags( display, data, 0 );
1378
1379 data->mapped = FALSE;
1380 data->net_wm_state = 0;
1381}
1382
1383
1384/***********************************************************************
1385 * make_window_embedded
1386 */
1387void make_window_embedded( Display *display, struct x11drv_win_data *data )
1388{
1389 if (data->mapped)
1390 {
1391 /* the window cannot be mapped before being embedded */
1392 unmap_window( display, data );
1393 data->embedded = TRUE;
1394 map_window( display, data, 0 );
1395 }
1396 else
1397 {
1398 data->embedded = TRUE;
1399 set_xembed_flags( display, data, 0 );
1400 }
1401}
1402
1403
1404/***********************************************************************
Alexandre Julliarddc4fe772001-06-04 21:55:17 +00001405 * X11DRV_window_to_X_rect
1406 *
1407 * Convert a rect from client to X window coordinates
1408 */
Andrew Talbotf63ceec2009-01-29 21:40:50 +00001409static void X11DRV_window_to_X_rect( struct x11drv_win_data *data, RECT *rect )
Alexandre Julliarddc4fe772001-06-04 21:55:17 +00001410{
Alexandre Julliard8cd1f712001-07-20 18:37:37 +00001411 RECT rc;
1412
Alexandre Julliardd7726c32005-02-01 18:53:59 +00001413 if (!data->managed) return;
Alexandre Julliarddc4fe772001-06-04 21:55:17 +00001414 if (IsRectEmpty( rect )) return;
1415
Alexandre Julliardc4e20e72007-10-11 12:24:27 +02001416 get_x11_rect_offset( data, &rc );
Alexandre Julliarddc4fe772001-06-04 21:55:17 +00001417
Alexandre Julliard8cd1f712001-07-20 18:37:37 +00001418 rect->left -= rc.left;
1419 rect->right -= rc.right;
1420 rect->top -= rc.top;
1421 rect->bottom -= rc.bottom;
Alexandre Julliarddc4fe772001-06-04 21:55:17 +00001422 if (rect->top >= rect->bottom) rect->bottom = rect->top + 1;
1423 if (rect->left >= rect->right) rect->right = rect->left + 1;
1424}
1425
1426
1427/***********************************************************************
1428 * X11DRV_X_to_window_rect
1429 *
1430 * Opposite of X11DRV_window_to_X_rect
1431 */
Alexandre Julliardd7726c32005-02-01 18:53:59 +00001432void X11DRV_X_to_window_rect( struct x11drv_win_data *data, RECT *rect )
Alexandre Julliarddc4fe772001-06-04 21:55:17 +00001433{
Alexandre Julliardc4e20e72007-10-11 12:24:27 +02001434 RECT rc;
Alexandre Julliard74cd76c2007-08-29 12:02:57 +02001435
Alexandre Julliardd7726c32005-02-01 18:53:59 +00001436 if (!data->managed) return;
Alexandre Julliarddc4fe772001-06-04 21:55:17 +00001437 if (IsRectEmpty( rect )) return;
1438
Alexandre Julliardc4e20e72007-10-11 12:24:27 +02001439 get_x11_rect_offset( data, &rc );
Alexandre Julliarddc4fe772001-06-04 21:55:17 +00001440
Alexandre Julliardc4e20e72007-10-11 12:24:27 +02001441 rect->left += rc.left;
1442 rect->right += rc.right;
1443 rect->top += rc.top;
1444 rect->bottom += rc.bottom;
Alexandre Julliarddc4fe772001-06-04 21:55:17 +00001445 if (rect->top >= rect->bottom) rect->bottom = rect->top + 1;
1446 if (rect->left >= rect->right) rect->right = rect->left + 1;
1447}
1448
1449
1450/***********************************************************************
Alexandre Julliard855308f2008-04-23 15:32:58 +02001451 * sync_window_position
Alexandre Julliarddc4fe772001-06-04 21:55:17 +00001452 *
Alexandre Julliardf777d702005-01-31 16:34:07 +00001453 * Synchronize the X window position with the Windows one
Alexandre Julliarddc4fe772001-06-04 21:55:17 +00001454 */
Alexandre Julliard855308f2008-04-23 15:32:58 +02001455static void sync_window_position( Display *display, struct x11drv_win_data *data,
Alexandre Julliard08b83252010-02-08 17:14:01 +01001456 UINT swp_flags, const RECT *old_window_rect,
1457 const RECT *old_whole_rect, const RECT *old_client_rect )
Alexandre Julliarddc4fe772001-06-04 21:55:17 +00001458{
Alexandre Julliardcef3bc62008-04-04 11:20:45 +02001459 DWORD style = GetWindowLongW( data->hwnd, GWL_STYLE );
Alexandre Julliarddc4fe772001-06-04 21:55:17 +00001460 XWindowChanges changes;
Alexandre Julliardbbd32aa2008-04-23 15:34:07 +02001461 unsigned int mask = 0;
Alexandre Julliardcef3bc62008-04-04 11:20:45 +02001462
1463 if (data->managed && data->iconic) return;
1464
Alexandre Julliardbbd32aa2008-04-23 15:34:07 +02001465 /* resizing a managed maximized window is not allowed */
1466 if (!(style & WS_MAXIMIZE) || !data->managed)
1467 {
Alexandre Julliard308476e2008-09-17 21:11:47 +02001468 changes.width = data->whole_rect.right - data->whole_rect.left;
1469 changes.height = data->whole_rect.bottom - data->whole_rect.top;
1470 /* if window rect is empty force size to 1x1 */
1471 if (changes.width <= 0 || changes.height <= 0) changes.width = changes.height = 1;
Alexandre Julliarda4644f12009-05-05 15:36:25 +02001472 if (changes.width > 65535) changes.width = 65535;
1473 if (changes.height > 65535) changes.height = 65535;
Alexandre Julliardbbd32aa2008-04-23 15:34:07 +02001474 mask |= CWWidth | CWHeight;
1475 }
Alexandre Julliardcef3bc62008-04-04 11:20:45 +02001476
1477 /* only the size is allowed to change for the desktop window */
1478 if (data->whole_window != root_window)
1479 {
1480 changes.x = data->whole_rect.left - virtual_screen_rect.left;
1481 changes.y = data->whole_rect.top - virtual_screen_rect.top;
1482 mask |= CWX | CWY;
1483 }
Alexandre Julliardf777d702005-01-31 16:34:07 +00001484
Alexandre Julliardac40efa2008-08-29 13:34:55 +02001485 if (!(swp_flags & SWP_NOZORDER) || (swp_flags & SWP_SHOWWINDOW))
Alexandre Julliarddc4fe772001-06-04 21:55:17 +00001486 {
Alexandre Julliardf777d702005-01-31 16:34:07 +00001487 /* find window that this one must be after */
1488 HWND prev = GetWindow( data->hwnd, GW_HWNDPREV );
1489 while (prev && !(GetWindowLongW( prev, GWL_STYLE ) & WS_VISIBLE))
1490 prev = GetWindow( prev, GW_HWNDPREV );
1491 if (!prev) /* top child */
Alexandre Julliarddc4fe772001-06-04 21:55:17 +00001492 {
Alexandre Julliardf777d702005-01-31 16:34:07 +00001493 changes.stack_mode = Above;
1494 mask |= CWStackMode;
Alexandre Julliarddc4fe772001-06-04 21:55:17 +00001495 }
Alexandre Julliard5787c122008-03-24 15:47:28 +01001496 /* should use stack_mode Below but most window managers don't get it right */
1497 /* and Above with a sibling doesn't work so well either, so we ignore it */
Alexandre Julliarddc4fe772001-06-04 21:55:17 +00001498 }
1499
Alexandre Julliardcef3bc62008-04-04 11:20:45 +02001500 wine_tsx11_lock();
1501 set_size_hints( display, data, style );
Alexandre Julliard00b06da2010-01-04 17:56:32 +01001502 data->configure_serial = NextRequest( display );
Alexandre Julliardcef3bc62008-04-04 11:20:45 +02001503 XReconfigureWMWindow( display, data->whole_window,
1504 DefaultScreen(display), mask, &changes );
Alexandre Julliard4c7b8ca2010-02-04 17:27:19 +01001505#ifdef HAVE_LIBXSHAPE
1506 if (data->shaped)
1507 {
Alexandre Julliard08b83252010-02-08 17:14:01 +01001508 int old_x_offset = old_window_rect->left - old_whole_rect->left;
1509 int old_y_offset = old_window_rect->top - old_whole_rect->top;
1510 int new_x_offset = data->window_rect.left - data->whole_rect.left;
1511 int new_y_offset = data->window_rect.top - data->whole_rect.top;
1512 if (old_x_offset != new_x_offset || old_y_offset != new_y_offset)
1513 XShapeOffsetShape( display, data->whole_window, ShapeBounding,
1514 new_x_offset - old_x_offset, new_y_offset - old_y_offset );
Alexandre Julliard4c7b8ca2010-02-04 17:27:19 +01001515 }
1516#endif
Alexandre Julliardcef3bc62008-04-04 11:20:45 +02001517 wine_tsx11_unlock();
Alexandre Julliard00b06da2010-01-04 17:56:32 +01001518
1519 TRACE( "win %p/%lx pos %d,%d,%dx%d after %lx changes=%x serial=%lu\n",
1520 data->hwnd, data->whole_window, data->whole_rect.left, data->whole_rect.top,
1521 data->whole_rect.right - data->whole_rect.left,
1522 data->whole_rect.bottom - data->whole_rect.top,
1523 changes.sibling, mask, data->configure_serial );
Alexandre Julliarddc4fe772001-06-04 21:55:17 +00001524}
1525
1526
Alexandre Julliard8ee07d42008-02-21 12:29:36 +01001527/***********************************************************************
Alexandre Julliard855308f2008-04-23 15:32:58 +02001528 * sync_client_position
Alexandre Julliard8ee07d42008-02-21 12:29:36 +01001529 *
1530 * Synchronize the X client window position with the Windows one
1531 */
Alexandre Julliard855308f2008-04-23 15:32:58 +02001532static void sync_client_position( Display *display, struct x11drv_win_data *data,
Alexandre Julliard8ee07d42008-02-21 12:29:36 +01001533 UINT swp_flags, const RECT *old_client_rect,
1534 const RECT *old_whole_rect )
1535{
1536 int mask;
1537 XWindowChanges changes;
1538 RECT old = *old_client_rect;
1539 RECT new = data->client_rect;
1540
1541 OffsetRect( &old, -old_whole_rect->left, -old_whole_rect->top );
1542 OffsetRect( &new, -data->whole_rect.left, -data->whole_rect.top );
1543 if (!(mask = get_window_changes( &changes, &old, &new ))) return;
1544
1545 if (data->client_window)
1546 {
1547 TRACE( "setting client win %lx pos %d,%d,%dx%d changes=%x\n",
1548 data->client_window, new.left, new.top,
1549 new.right - new.left, new.bottom - new.top, mask );
1550 wine_tsx11_lock();
1551 XConfigureWindow( display, data->client_window, mask, &changes );
1552 wine_tsx11_unlock();
1553 }
1554
Alexandre Julliard6e9dea82008-05-12 19:37:54 +02001555 if (data->gl_drawable && (mask & (CWWidth|CWHeight))) sync_gl_drawable( data );
Alexandre Julliard8ee07d42008-02-21 12:29:36 +01001556}
1557
1558
Alexandre Julliard855308f2008-04-23 15:32:58 +02001559/***********************************************************************
1560 * move_window_bits
1561 *
1562 * Move the window bits when a window is moved.
1563 */
1564static void move_window_bits( struct x11drv_win_data *data, const RECT *old_rect, const RECT *new_rect,
1565 const RECT *old_client_rect )
1566{
1567 RECT src_rect = *old_rect;
1568 RECT dst_rect = *new_rect;
1569 HDC hdc_src, hdc_dst;
1570 INT code;
1571 HRGN rgn = 0;
1572 HWND parent = 0;
1573
1574 if (!data->whole_window)
1575 {
1576 OffsetRect( &dst_rect, -data->window_rect.left, -data->window_rect.top );
1577 parent = GetAncestor( data->hwnd, GA_PARENT );
1578 hdc_src = GetDCEx( parent, 0, DCX_CACHE );
1579 hdc_dst = GetDCEx( data->hwnd, 0, DCX_CACHE | DCX_WINDOW );
1580 }
1581 else
1582 {
1583 OffsetRect( &dst_rect, -data->client_rect.left, -data->client_rect.top );
1584 /* make src rect relative to the old position of the window */
1585 OffsetRect( &src_rect, -old_client_rect->left, -old_client_rect->top );
1586 if (dst_rect.left == src_rect.left && dst_rect.top == src_rect.top) return;
1587 hdc_src = hdc_dst = GetDCEx( data->hwnd, 0, DCX_CACHE );
1588 }
1589
1590 code = X11DRV_START_EXPOSURES;
1591 ExtEscape( hdc_dst, X11DRV_ESCAPE, sizeof(code), (LPSTR)&code, 0, NULL );
1592
1593 TRACE( "copying bits for win %p/%lx/%lx %s -> %s\n",
1594 data->hwnd, data->whole_window, data->client_window,
1595 wine_dbgstr_rect(&src_rect), wine_dbgstr_rect(&dst_rect) );
1596 BitBlt( hdc_dst, dst_rect.left, dst_rect.top,
1597 dst_rect.right - dst_rect.left, dst_rect.bottom - dst_rect.top,
1598 hdc_src, src_rect.left, src_rect.top, SRCCOPY );
1599
1600 code = X11DRV_END_EXPOSURES;
1601 ExtEscape( hdc_dst, X11DRV_ESCAPE, sizeof(code), (LPSTR)&code, sizeof(rgn), (LPSTR)&rgn );
1602
1603 ReleaseDC( data->hwnd, hdc_dst );
1604 if (hdc_src != hdc_dst) ReleaseDC( parent, hdc_src );
1605
1606 if (rgn)
1607 {
1608 if (!data->whole_window)
1609 {
1610 /* map region to client rect since we are using DCX_WINDOW */
1611 OffsetRgn( rgn, data->window_rect.left - data->client_rect.left,
1612 data->window_rect.top - data->client_rect.top );
1613 RedrawWindow( data->hwnd, NULL, rgn,
1614 RDW_INVALIDATE | RDW_FRAME | RDW_ERASE | RDW_ALLCHILDREN );
1615 }
1616 else RedrawWindow( data->hwnd, NULL, rgn, RDW_INVALIDATE | RDW_ERASE | RDW_ALLCHILDREN );
1617 DeleteObject( rgn );
1618 }
1619}
1620
1621
Alexandre Julliard9ae0fe52001-04-24 23:28:52 +00001622/**********************************************************************
Alexandre Julliarddc4fe772001-06-04 21:55:17 +00001623 * create_whole_window
1624 *
1625 * Create the whole X window for a given window
Alexandre Julliard9ae0fe52001-04-24 23:28:52 +00001626 */
Alexandre Julliardd147e022008-01-23 21:39:32 +01001627static Window create_whole_window( Display *display, struct x11drv_win_data *data )
Alexandre Julliarddc4fe772001-06-04 21:55:17 +00001628{
Alexandre Julliarddc4fe772001-06-04 21:55:17 +00001629 int cx, cy, mask;
1630 XSetWindowAttributes attr;
Alexandre Julliard3ba20252008-01-23 16:32:55 +01001631 WCHAR text[1024];
Alexandre Julliardbe3c3a52008-09-12 15:54:02 +02001632 COLORREF key;
1633 BYTE alpha;
1634 DWORD layered_flags;
Alexandre Julliardaa477842010-02-01 22:35:32 +01001635 HRGN win_rgn;
Alexandre Julliarddc4fe772001-06-04 21:55:17 +00001636
Alexandre Julliarde6dfbcb2008-01-25 12:07:11 +01001637 if (!data->managed && is_window_managed( data->hwnd, SWP_NOACTIVATE, &data->window_rect ))
1638 {
1639 TRACE( "making win %p/%lx managed\n", data->hwnd, data->whole_window );
1640 data->managed = TRUE;
1641 SetPropA( data->hwnd, managed_prop, (HANDLE)1 );
1642 }
1643
Alexandre Julliardaa477842010-02-01 22:35:32 +01001644 if ((win_rgn = CreateRectRgn( 0, 0, 0, 0 )) &&
1645 GetWindowRgn( data->hwnd, win_rgn ) == ERROR)
1646 {
1647 DeleteObject( win_rgn );
1648 win_rgn = 0;
1649 }
1650 data->shaped = (win_rgn != 0);
1651
Alexandre Julliard6bb18e22006-03-27 15:33:43 +02001652 mask = get_window_attributes( display, data, &attr );
Alexandre Julliard883cff42001-06-12 04:02:10 +00001653
Alexandre Julliardac98e0c2007-08-20 22:06:33 +02001654 data->whole_rect = data->window_rect;
Alexandre Julliardedebc2b2009-06-25 12:10:44 +02001655 X11DRV_window_to_X_rect( data, &data->whole_rect );
1656 if (!(cx = data->whole_rect.right - data->whole_rect.left)) cx = 1;
1657 else if (cx > 65535) cx = 65535;
1658 if (!(cy = data->whole_rect.bottom - data->whole_rect.top)) cy = 1;
1659 else if (cy > 65535) cy = 65535;
1660
1661 wine_tsx11_lock();
Alexandre Julliarda06aeab2006-10-26 12:53:59 +02001662 data->whole_window = XCreateWindow( display, root_window,
Alexandre Julliardedebc2b2009-06-25 12:10:44 +02001663 data->whole_rect.left - virtual_screen_rect.left,
1664 data->whole_rect.top - virtual_screen_rect.top,
Alexandre Julliarda06aeab2006-10-26 12:53:59 +02001665 cx, cy, 0, screen_depth, InputOutput,
1666 visual, mask, &attr );
Alexandre Julliarddc4fe772001-06-04 21:55:17 +00001667
Alexandre Julliard42ad3452008-02-22 10:40:22 +01001668 if (data->whole_window) XSaveContext( display, data->whole_window, winContext, (char *)data->hwnd );
1669 wine_tsx11_unlock();
1670
Alexandre Julliardaa477842010-02-01 22:35:32 +01001671 if (!data->whole_window) goto done;
Alexandre Julliard42ad3452008-02-22 10:40:22 +01001672
1673 if (!create_client_window( display, data, NULL ))
Alexandre Julliard704d0352001-07-12 02:49:31 +00001674 {
Alexandre Julliard42ad3452008-02-22 10:40:22 +01001675 wine_tsx11_lock();
1676 XDeleteContext( display, data->whole_window, winContext );
Alexandre Julliard8ee07d42008-02-21 12:29:36 +01001677 XDestroyWindow( display, data->whole_window );
1678 data->whole_window = 0;
1679 wine_tsx11_unlock();
Alexandre Julliardaa477842010-02-01 22:35:32 +01001680 goto done;
Alexandre Julliard8ee07d42008-02-21 12:29:36 +01001681 }
1682
Alexandre Julliard7d9739e2007-08-20 14:04:36 +02001683 set_initial_wm_hints( display, data );
Alexandre Julliard855308f2008-04-23 15:32:58 +02001684 set_wm_hints( display, data );
Alexandre Julliardf777d702005-01-31 16:34:07 +00001685
Alexandre Julliardaf50ad62005-07-07 17:30:57 +00001686 SetPropA( data->hwnd, whole_window_prop, (HANDLE)data->whole_window );
Alexandre Julliard395928d2008-01-23 16:30:18 +01001687
Alexandre Julliard3ba20252008-01-23 16:32:55 +01001688 /* set the window text */
1689 if (!InternalGetWindowText( data->hwnd, text, sizeof(text)/sizeof(WCHAR) )) text[0] = 0;
1690 sync_window_text( display, data->whole_window, text );
1691
Alexandre Julliard395928d2008-01-23 16:30:18 +01001692 /* set the window region */
Alexandre Julliardaa477842010-02-01 22:35:32 +01001693 if (win_rgn) sync_window_region( display, data, win_rgn );
Alexandre Julliard9d45cfd2008-09-08 15:51:08 +02001694
Alexandre Julliardbe3c3a52008-09-12 15:54:02 +02001695 /* set the window opacity */
1696 if (!GetLayeredWindowAttributes( data->hwnd, &key, &alpha, &layered_flags )) layered_flags = 0;
1697 sync_window_opacity( display, data->whole_window, key, alpha, layered_flags );
1698
Alexandre Julliard731d77f2008-04-09 20:24:27 +02001699 wine_tsx11_lock();
1700 XFlush( display ); /* make sure the window exists before we start painting to it */
1701 wine_tsx11_unlock();
Alexandre Julliard1afd0df2010-05-10 12:33:59 +02001702
1703 sync_window_cursor( data );
Alexandre Julliardaa477842010-02-01 22:35:32 +01001704done:
1705 if (win_rgn) DeleteObject( win_rgn );
Alexandre Julliarddc4fe772001-06-04 21:55:17 +00001706 return data->whole_window;
1707}
1708
1709
1710/**********************************************************************
Alexandre Julliardf777d702005-01-31 16:34:07 +00001711 * destroy_whole_window
Alexandre Julliarddc4fe772001-06-04 21:55:17 +00001712 *
Alexandre Julliardf777d702005-01-31 16:34:07 +00001713 * Destroy the whole X window for a given window.
Alexandre Julliarddc4fe772001-06-04 21:55:17 +00001714 */
Alexandre Julliard3b6f95c2008-03-05 16:51:09 +01001715static void destroy_whole_window( Display *display, struct x11drv_win_data *data, BOOL already_destroyed )
Alexandre Julliarddc4fe772001-06-04 21:55:17 +00001716{
Alexandre Julliardf777d702005-01-31 16:34:07 +00001717 if (!data->whole_window) return;
Alexandre Julliarddc4fe772001-06-04 21:55:17 +00001718
Alexandre Julliard8ee07d42008-02-21 12:29:36 +01001719 TRACE( "win %p xwin %lx/%lx\n", data->hwnd, data->whole_window, data->client_window );
Alexandre Julliard883cff42001-06-12 04:02:10 +00001720 wine_tsx11_lock();
Alexandre Julliardf777d702005-01-31 16:34:07 +00001721 XDeleteContext( display, data->whole_window, winContext );
Alexandre Julliard8ee07d42008-02-21 12:29:36 +01001722 XDeleteContext( display, data->client_window, winContext );
Alexandre Julliard3b6f95c2008-03-05 16:51:09 +01001723 if (!already_destroyed) XDestroyWindow( display, data->whole_window );
Alexandre Julliard8ee07d42008-02-21 12:29:36 +01001724 data->whole_window = data->client_window = 0;
Alexandre Julliard3b6f95c2008-03-05 16:51:09 +01001725 data->wm_state = WithdrawnState;
1726 data->net_wm_state = 0;
1727 data->mapped = FALSE;
Alexandre Julliardf777d702005-01-31 16:34:07 +00001728 if (data->xic)
1729 {
1730 XUnsetICFocus( data->xic );
1731 XDestroyIC( data->xic );
Alexandre Julliard3b6f95c2008-03-05 16:51:09 +01001732 data->xic = 0;
Alexandre Julliardf777d702005-01-31 16:34:07 +00001733 }
Alexandre Julliard975f1b22006-05-09 17:32:40 +02001734 /* Outlook stops processing messages after destroying a dialog, so we need an explicit flush */
1735 XFlush( display );
Alexandre Julliarddc07b6f2008-01-22 10:17:52 +01001736 XFree( data->wm_hints );
1737 data->wm_hints = NULL;
Alexandre Julliard883cff42001-06-12 04:02:10 +00001738 wine_tsx11_unlock();
Alexandre Julliardaf50ad62005-07-07 17:30:57 +00001739 RemovePropA( data->hwnd, whole_window_prop );
Alexandre Julliard8ee07d42008-02-21 12:29:36 +01001740 RemovePropA( data->hwnd, client_window_prop );
Alexandre Julliarddc4fe772001-06-04 21:55:17 +00001741}
1742
1743
1744/*****************************************************************
1745 * SetWindowText (X11DRV.@)
1746 */
Maarten Lankhorst0a645952008-12-16 15:32:08 +01001747void CDECL X11DRV_SetWindowText( HWND hwnd, LPCWSTR text )
Alexandre Julliard9ae0fe52001-04-24 23:28:52 +00001748{
Alexandre Julliarddc4fe772001-06-04 21:55:17 +00001749 Window win;
Alexandre Julliard9ae0fe52001-04-24 23:28:52 +00001750
Alexandre Julliarde7044cb2008-06-26 16:47:42 +02001751 if ((win = X11DRV_get_whole_window( hwnd )) && win != DefaultRootWindow(gdi_display))
1752 {
1753 Display *display = thread_init_display();
Alexandre Julliard3ba20252008-01-23 16:32:55 +01001754 sync_window_text( display, win, text );
Alexandre Julliarde7044cb2008-06-26 16:47:42 +02001755 }
Alexandre Julliard9ae0fe52001-04-24 23:28:52 +00001756}
1757
1758
1759/***********************************************************************
Alexandre Julliard855308f2008-04-23 15:32:58 +02001760 * SetWindowStyle (X11DRV.@)
1761 *
1762 * Update the X state of a window to reflect a style change
1763 */
Maarten Lankhorst0a645952008-12-16 15:32:08 +01001764void CDECL X11DRV_SetWindowStyle( HWND hwnd, INT offset, STYLESTRUCT *style )
Alexandre Julliard855308f2008-04-23 15:32:58 +02001765{
Alexandre Julliard855308f2008-04-23 15:32:58 +02001766 struct x11drv_win_data *data;
Alexandre Julliard2f112132008-09-12 14:55:07 +02001767 DWORD changed;
Alexandre Julliard855308f2008-04-23 15:32:58 +02001768
1769 if (hwnd == GetDesktopWindow()) return;
Alexandre Julliard2f112132008-09-12 14:55:07 +02001770 changed = style->styleNew ^ style->styleOld;
Alexandre Julliard855308f2008-04-23 15:32:58 +02001771
Alexandre Julliard2f112132008-09-12 14:55:07 +02001772 if (offset == GWL_STYLE && (changed & WS_VISIBLE) && (style->styleNew & WS_VISIBLE))
Alexandre Julliard855308f2008-04-23 15:32:58 +02001773 {
1774 /* we don't unmap windows, that causes trouble with the window manager */
1775 if (!(data = X11DRV_get_win_data( hwnd )) &&
1776 !(data = X11DRV_create_win_data( hwnd ))) return;
1777
1778 if (data->whole_window && is_window_rect_mapped( &data->window_rect ))
1779 {
Alexandre Julliarde7044cb2008-06-26 16:47:42 +02001780 Display *display = thread_display();
Alexandre Julliard855308f2008-04-23 15:32:58 +02001781 set_wm_hints( display, data );
Alexandre Julliard2f112132008-09-12 14:55:07 +02001782 if (!data->mapped) map_window( display, data, style->styleNew );
Alexandre Julliard855308f2008-04-23 15:32:58 +02001783 }
1784 }
1785
Alexandre Julliard2f112132008-09-12 14:55:07 +02001786 if (offset == GWL_STYLE && (changed & WS_DISABLED))
Alexandre Julliard855308f2008-04-23 15:32:58 +02001787 {
1788 data = X11DRV_get_win_data( hwnd );
Dmitry Timoshkove35e75b2010-04-07 15:41:01 +09001789 if (data && data->whole_window)
1790 set_wm_hints( thread_display(), data );
Alexandre Julliard855308f2008-04-23 15:32:58 +02001791 }
Alexandre Julliardbe3c3a52008-09-12 15:54:02 +02001792
1793 if (offset == GWL_EXSTYLE && (changed & WS_EX_LAYERED))
1794 {
1795 /* changing WS_EX_LAYERED resets attributes */
1796 if ((data = X11DRV_get_win_data( hwnd )) && data->whole_window)
1797 sync_window_opacity( thread_display(), data->whole_window, 0, 0, 0 );
1798 }
Alexandre Julliard855308f2008-04-23 15:32:58 +02001799}
1800
1801
1802/***********************************************************************
Alexandre Julliard9ae0fe52001-04-24 23:28:52 +00001803 * DestroyWindow (X11DRV.@)
1804 */
Maarten Lankhorst0a645952008-12-16 15:32:08 +01001805void CDECL X11DRV_DestroyWindow( HWND hwnd )
Alexandre Julliard9ae0fe52001-04-24 23:28:52 +00001806{
Alexandre Julliard9428f062002-06-14 00:08:40 +00001807 struct x11drv_thread_data *thread_data = x11drv_thread_data();
Alexandre Julliardd56ccaa2005-01-28 17:25:50 +00001808 struct x11drv_win_data *data;
Alexandre Julliard9ae0fe52001-04-24 23:28:52 +00001809
Alexandre Julliard2997fc52005-07-18 13:20:18 +00001810 if (!(data = X11DRV_get_win_data( hwnd ))) return;
Alexandre Julliarddc4fe772001-06-04 21:55:17 +00001811
Chris Robinson37d835b2007-09-26 08:17:13 -07001812 if (data->pixmap)
1813 {
Chris Robinson37d835b2007-09-26 08:17:13 -07001814 wine_tsx11_lock();
Alexandre Julliard6e9dea82008-05-12 19:37:54 +02001815 destroy_glxpixmap(gdi_display, data->gl_drawable);
1816 XFreePixmap(gdi_display, data->pixmap);
Chris Robinson37d835b2007-09-26 08:17:13 -07001817 wine_tsx11_unlock();
1818 }
1819 else if (data->gl_drawable)
Chris Robinson00633e32007-09-25 22:43:38 -07001820 {
1821 wine_tsx11_lock();
Alexandre Julliard6e9dea82008-05-12 19:37:54 +02001822 XDestroyWindow(gdi_display, data->gl_drawable);
Chris Robinson00633e32007-09-25 22:43:38 -07001823 wine_tsx11_unlock();
1824 }
1825
Alexandre Julliard06a14072008-06-26 15:08:08 +02001826 destroy_whole_window( thread_data->display, data, FALSE );
1827 destroy_icon_window( thread_data->display, data );
Alexandre Julliarddc4fe772001-06-04 21:55:17 +00001828
Alexandre Julliarde9307d02008-02-21 20:23:32 +01001829 if (data->colormap)
1830 {
1831 wine_tsx11_lock();
Alexandre Julliard06a14072008-06-26 15:08:08 +02001832 XFreeColormap( thread_data->display, data->colormap );
Alexandre Julliarde9307d02008-02-21 20:23:32 +01001833 wine_tsx11_unlock();
1834 }
1835
Alexandre Julliardf777d702005-01-31 16:34:07 +00001836 if (thread_data->last_focus == hwnd) thread_data->last_focus = 0;
Alexandre Julliarddc4fe772001-06-04 21:55:17 +00001837 if (data->hWMIconBitmap) DeleteObject( data->hWMIconBitmap );
1838 if (data->hWMIconMask) DeleteObject( data->hWMIconMask);
Alexandre Julliardd56ccaa2005-01-28 17:25:50 +00001839 wine_tsx11_lock();
Alexandre Julliard06a14072008-06-26 15:08:08 +02001840 XDeleteContext( thread_data->display, (XID)hwnd, win_data_context );
Alexandre Julliardd56ccaa2005-01-28 17:25:50 +00001841 wine_tsx11_unlock();
Alexandre Julliard9ae0fe52001-04-24 23:28:52 +00001842 HeapFree( GetProcessHeap(), 0, data );
Alexandre Julliard9ae0fe52001-04-24 23:28:52 +00001843}
1844
1845
Alexandre Julliard3b6f95c2008-03-05 16:51:09 +01001846/***********************************************************************
1847 * X11DRV_DestroyNotify
1848 */
1849void X11DRV_DestroyNotify( HWND hwnd, XEvent *event )
1850{
1851 Display *display = event->xdestroywindow.display;
1852 struct x11drv_win_data *data;
1853
1854 if (!(data = X11DRV_get_win_data( hwnd ))) return;
1855
1856 FIXME( "window %p/%lx destroyed from the outside\n", hwnd, data->whole_window );
1857 destroy_whole_window( display, data, TRUE );
1858}
1859
1860
Alexandre Julliarde419cb82005-07-07 20:33:29 +00001861static struct x11drv_win_data *alloc_win_data( Display *display, HWND hwnd )
1862{
1863 struct x11drv_win_data *data;
1864
Alexandre Julliard30d84fc2008-01-22 10:15:38 +01001865 if ((data = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*data))))
Alexandre Julliarde419cb82005-07-07 20:33:29 +00001866 {
Alexandre Julliard30d84fc2008-01-22 10:15:38 +01001867 data->hwnd = hwnd;
Alexandre Julliarde419cb82005-07-07 20:33:29 +00001868 wine_tsx11_lock();
1869 if (!winContext) winContext = XUniqueContext();
1870 if (!win_data_context) win_data_context = XUniqueContext();
1871 XSaveContext( display, (XID)hwnd, win_data_context, (char *)data );
1872 wine_tsx11_unlock();
1873 }
1874 return data;
1875}
1876
1877
Alexandre Julliardc19af912008-01-17 19:53:59 +01001878/* initialize the desktop window id in the desktop manager process */
Alexandre Julliardb6cc7f92008-01-24 10:20:11 +01001879static struct x11drv_win_data *create_desktop_win_data( Display *display, HWND hwnd )
Alexandre Julliarddb6608a2006-03-27 22:43:03 +02001880{
Alexandre Julliardb6cc7f92008-01-24 10:20:11 +01001881 struct x11drv_win_data *data;
Alexandre Julliarddb6608a2006-03-27 22:43:03 +02001882
Alexandre Julliardb6cc7f92008-01-24 10:20:11 +01001883 if (!(data = alloc_win_data( display, hwnd ))) return NULL;
Alexandre Julliard8ee07d42008-02-21 12:29:36 +01001884 data->whole_window = data->client_window = root_window;
Alexandre Julliardb6cc7f92008-01-24 10:20:11 +01001885 data->managed = TRUE;
1886 SetPropA( data->hwnd, managed_prop, (HANDLE)1 );
1887 SetPropA( data->hwnd, whole_window_prop, (HANDLE)root_window );
Alexandre Julliard8ee07d42008-02-21 12:29:36 +01001888 SetPropA( data->hwnd, client_window_prop, (HANDLE)root_window );
Alexandre Julliardb6cc7f92008-01-24 10:20:11 +01001889 set_initial_wm_hints( display, data );
1890 return data;
Alexandre Julliarddb6608a2006-03-27 22:43:03 +02001891}
1892
Alexandre Julliarde419cb82005-07-07 20:33:29 +00001893/**********************************************************************
1894 * CreateDesktopWindow (X11DRV.@)
1895 */
Maarten Lankhorst0a645952008-12-16 15:32:08 +01001896BOOL CDECL X11DRV_CreateDesktopWindow( HWND hwnd )
Alexandre Julliarde419cb82005-07-07 20:33:29 +00001897{
Alexandre Julliardc19af912008-01-17 19:53:59 +01001898 unsigned int width, height;
Alexandre Julliarde419cb82005-07-07 20:33:29 +00001899
Alexandre Julliardc19af912008-01-17 19:53:59 +01001900 /* retrieve the real size of the desktop */
1901 SERVER_START_REQ( get_window_rectangles )
1902 {
Alexandre Julliard7fdadbb2008-12-08 16:58:20 +01001903 req->handle = wine_server_user_handle( hwnd );
Alexandre Julliardc19af912008-01-17 19:53:59 +01001904 wine_server_call( req );
1905 width = reply->window.right - reply->window.left;
1906 height = reply->window.bottom - reply->window.top;
1907 }
1908 SERVER_END_REQ;
Alexandre Julliarde419cb82005-07-07 20:33:29 +00001909
Alexandre Julliardc19af912008-01-17 19:53:59 +01001910 if (!width && !height) /* not initialized yet */
1911 {
1912 SERVER_START_REQ( set_window_pos )
1913 {
Alexandre Julliard7fdadbb2008-12-08 16:58:20 +01001914 req->handle = wine_server_user_handle( hwnd );
Alexandre Julliardc19af912008-01-17 19:53:59 +01001915 req->previous = 0;
1916 req->flags = SWP_NOZORDER;
1917 req->window.left = virtual_screen_rect.left;
1918 req->window.top = virtual_screen_rect.top;
1919 req->window.right = virtual_screen_rect.right;
1920 req->window.bottom = virtual_screen_rect.bottom;
1921 req->client = req->window;
1922 wine_server_call( req );
1923 }
1924 SERVER_END_REQ;
1925 }
1926 else
1927 {
1928 Window win = (Window)GetPropA( hwnd, whole_window_prop );
1929 if (win && win != root_window) X11DRV_init_desktop( win, width, height );
1930 }
Alexandre Julliarde419cb82005-07-07 20:33:29 +00001931 return TRUE;
1932}
1933
1934
Alexandre Julliarddc4fe772001-06-04 21:55:17 +00001935/**********************************************************************
1936 * CreateWindow (X11DRV.@)
1937 */
Maarten Lankhorst0a645952008-12-16 15:32:08 +01001938BOOL CDECL X11DRV_CreateWindow( HWND hwnd )
Alexandre Julliarddc4fe772001-06-04 21:55:17 +00001939{
Alexandre Julliarde7044cb2008-06-26 16:47:42 +02001940 if (hwnd == GetDesktopWindow() && root_window != DefaultRootWindow( gdi_display ))
Alexandre Julliardb6cc7f92008-01-24 10:20:11 +01001941 {
Alexandre Julliarde7044cb2008-06-26 16:47:42 +02001942 Display *display = thread_init_display();
1943
Alexandre Julliard026974f2008-01-24 10:20:51 +01001944 /* the desktop win data can't be created lazily */
1945 if (!create_desktop_win_data( display, hwnd )) return FALSE;
Alexandre Julliarddb6608a2006-03-27 22:43:03 +02001946 }
Alexandre Julliarddc4fe772001-06-04 21:55:17 +00001947 return TRUE;
Alexandre Julliarddc4fe772001-06-04 21:55:17 +00001948}
1949
1950
1951/***********************************************************************
Alexandre Julliardfc5ce142005-01-17 19:17:47 +00001952 * X11DRV_get_win_data
1953 *
1954 * Return the X11 data structure associated with a window.
1955 */
1956struct x11drv_win_data *X11DRV_get_win_data( HWND hwnd )
1957{
Alexandre Julliard06a14072008-06-26 15:08:08 +02001958 struct x11drv_thread_data *thread_data = x11drv_thread_data();
Alexandre Julliardd56ccaa2005-01-28 17:25:50 +00001959 char *data;
Alexandre Julliarde5515552005-02-09 14:01:40 +00001960
Alexandre Julliard06a14072008-06-26 15:08:08 +02001961 if (!thread_data) return NULL;
1962 if (!hwnd) return NULL;
1963 if (XFindContext( thread_data->display, (XID)hwnd, win_data_context, &data )) data = NULL;
Alexandre Julliardd56ccaa2005-01-28 17:25:50 +00001964 return (struct x11drv_win_data *)data;
Alexandre Julliardfc5ce142005-01-17 19:17:47 +00001965}
1966
1967
1968/***********************************************************************
Alexandre Julliard026974f2008-01-24 10:20:51 +01001969 * X11DRV_create_win_data
1970 *
1971 * Create an X11 data window structure for an existing window.
1972 */
1973struct x11drv_win_data *X11DRV_create_win_data( HWND hwnd )
1974{
Alexandre Julliarde7044cb2008-06-26 16:47:42 +02001975 Display *display;
Alexandre Julliard026974f2008-01-24 10:20:51 +01001976 struct x11drv_win_data *data;
1977 HWND parent;
1978
1979 if (!(parent = GetAncestor( hwnd, GA_PARENT ))) return NULL; /* desktop */
Alexandre Julliarde7044cb2008-06-26 16:47:42 +02001980
Alexandre Julliard93a02e72008-06-26 16:49:09 +02001981 /* don't create win data for HWND_MESSAGE windows */
1982 if (parent != GetDesktopWindow() && !GetAncestor( parent, GA_PARENT )) return NULL;
1983
Alexandre Julliarde7044cb2008-06-26 16:47:42 +02001984 display = thread_init_display();
Alexandre Julliard026974f2008-01-24 10:20:51 +01001985 if (!(data = alloc_win_data( display, hwnd ))) return NULL;
1986
1987 GetWindowRect( hwnd, &data->window_rect );
1988 MapWindowPoints( 0, parent, (POINT *)&data->window_rect, 2 );
1989 data->whole_rect = data->window_rect;
1990 GetClientRect( hwnd, &data->client_rect );
1991 MapWindowPoints( hwnd, parent, (POINT *)&data->client_rect, 2 );
1992
1993 if (parent == GetDesktopWindow())
1994 {
1995 if (!create_whole_window( display, data ))
1996 {
1997 HeapFree( GetProcessHeap(), 0, data );
1998 return NULL;
1999 }
Alexandre Julliard8ee07d42008-02-21 12:29:36 +01002000 TRACE( "win %p/%lx/%lx window %s whole %s client %s\n",
2001 hwnd, data->whole_window, data->client_window, wine_dbgstr_rect( &data->window_rect ),
Alexandre Julliard026974f2008-01-24 10:20:51 +01002002 wine_dbgstr_rect( &data->whole_rect ), wine_dbgstr_rect( &data->client_rect ));
2003 }
Alexandre Julliard026974f2008-01-24 10:20:51 +01002004 return data;
2005}
2006
2007
2008/***********************************************************************
Alexandre Julliarddc4fe772001-06-04 21:55:17 +00002009 * X11DRV_get_whole_window
2010 *
2011 * Return the X window associated with the full area of a window
2012 */
2013Window X11DRV_get_whole_window( HWND hwnd )
2014{
Alexandre Julliardfc5ce142005-01-17 19:17:47 +00002015 struct x11drv_win_data *data = X11DRV_get_win_data( hwnd );
Alexandre Julliard8fd26b92001-10-15 17:56:45 +00002016
Alexandre Julliardc19af912008-01-17 19:53:59 +01002017 if (!data)
2018 {
2019 if (hwnd == GetDesktopWindow()) return root_window;
2020 return (Window)GetPropA( hwnd, whole_window_prop );
2021 }
Alexandre Julliardfc5ce142005-01-17 19:17:47 +00002022 return data->whole_window;
Alexandre Julliarddc4fe772001-06-04 21:55:17 +00002023}
2024
2025
Alexandre Julliard8b6a2192003-01-23 01:28:12 +00002026/***********************************************************************
Alexandre Julliard8ee07d42008-02-21 12:29:36 +01002027 * X11DRV_get_client_window
2028 *
2029 * Return the X window associated with the client area of a window
2030 */
Andrew Talbotf63ceec2009-01-29 21:40:50 +00002031static Window X11DRV_get_client_window( HWND hwnd )
Alexandre Julliard8ee07d42008-02-21 12:29:36 +01002032{
2033 struct x11drv_win_data *data = X11DRV_get_win_data( hwnd );
2034
2035 if (!data)
2036 {
2037 if (hwnd == GetDesktopWindow()) return root_window;
2038 return (Window)GetPropA( hwnd, client_window_prop );
2039 }
2040 return data->client_window;
2041}
2042
2043
2044/***********************************************************************
Alexandre Julliard8b6a2192003-01-23 01:28:12 +00002045 * X11DRV_get_ic
2046 *
2047 * Return the X input context associated with a window
2048 */
2049XIC X11DRV_get_ic( HWND hwnd )
2050{
Alexandre Julliardfc5ce142005-01-17 19:17:47 +00002051 struct x11drv_win_data *data = X11DRV_get_win_data( hwnd );
Kusanagi Kouichi185157c2008-04-04 20:44:36 +09002052 XIM xim;
Alexandre Julliard8b6a2192003-01-23 01:28:12 +00002053
Alexandre Julliardfc5ce142005-01-17 19:17:47 +00002054 if (!data) return 0;
Kusanagi Kouichi185157c2008-04-04 20:44:36 +09002055 if (data->xic) return data->xic;
2056 if (!(xim = x11drv_thread_data()->xim)) return 0;
2057 return X11DRV_CreateIC( xim, data );
Alexandre Julliard8b6a2192003-01-23 01:28:12 +00002058}
2059
2060
Alexandre Julliard1642fbc2008-02-25 15:59:19 +01002061/***********************************************************************
2062 * X11DRV_GetDC (X11DRV.@)
2063 */
Maarten Lankhorst0a645952008-12-16 15:32:08 +01002064void CDECL X11DRV_GetDC( HDC hdc, HWND hwnd, HWND top, const RECT *win_rect,
2065 const RECT *top_rect, DWORD flags )
Alexandre Julliard1642fbc2008-02-25 15:59:19 +01002066{
2067 struct x11drv_escape_set_drawable escape;
2068 struct x11drv_win_data *data = X11DRV_get_win_data( hwnd );
2069
2070 escape.code = X11DRV_SET_DRAWABLE;
2071 escape.mode = IncludeInferiors;
2072 escape.fbconfig_id = 0;
2073 escape.gl_drawable = 0;
2074 escape.pixmap = 0;
Alexandre Julliard2d9b3812008-05-28 17:52:06 +02002075 escape.gl_copy = FALSE;
Alexandre Julliard1642fbc2008-02-25 15:59:19 +01002076
Henri Verbeet3255b212010-04-11 21:47:49 +02002077 if (top == hwnd)
Alexandre Julliard1642fbc2008-02-25 15:59:19 +01002078 {
Alexandre Julliard2d9b3812008-05-28 17:52:06 +02002079 escape.fbconfig_id = data ? data->fbconfig_id : (XID)GetPropA( hwnd, fbconfig_id_prop );
2080 /* GL draws to the client area even for window DCs */
2081 escape.gl_drawable = data ? data->client_window : X11DRV_get_client_window( hwnd );
Henri Verbeet3255b212010-04-11 21:47:49 +02002082 if (data && IsIconic( hwnd ) && data->icon_window)
2083 {
2084 escape.drawable = data->icon_window;
2085 }
2086 else if (flags & DCX_WINDOW)
Alexandre Julliard2d9b3812008-05-28 17:52:06 +02002087 escape.drawable = data ? data->whole_window : X11DRV_get_whole_window( hwnd );
2088 else
2089 escape.drawable = escape.gl_drawable;
Alexandre Julliard1642fbc2008-02-25 15:59:19 +01002090 }
2091 else
2092 {
2093 escape.drawable = X11DRV_get_client_window( top );
2094 escape.fbconfig_id = data ? data->fbconfig_id : (XID)GetPropA( hwnd, fbconfig_id_prop );
2095 escape.gl_drawable = data ? data->gl_drawable : (Drawable)GetPropA( hwnd, gl_drawable_prop );
2096 escape.pixmap = data ? data->pixmap : (Pixmap)GetPropA( hwnd, pixmap_prop );
Alexandre Julliard2d9b3812008-05-28 17:52:06 +02002097 escape.gl_copy = (escape.gl_drawable != 0);
Alexandre Julliardaf369102008-03-18 12:42:25 +01002098 if (flags & DCX_CLIPCHILDREN) escape.mode = ClipByChildren;
Alexandre Julliard1642fbc2008-02-25 15:59:19 +01002099 }
2100
2101 escape.dc_rect.left = win_rect->left - top_rect->left;
2102 escape.dc_rect.top = win_rect->top - top_rect->top;
2103 escape.dc_rect.right = win_rect->right - top_rect->left;
2104 escape.dc_rect.bottom = win_rect->bottom - top_rect->top;
2105 escape.drawable_rect.left = top_rect->left;
2106 escape.drawable_rect.top = top_rect->top;
2107 escape.drawable_rect.right = top_rect->right;
2108 escape.drawable_rect.bottom = top_rect->bottom;
2109
2110 ExtEscape( hdc, X11DRV_ESCAPE, sizeof(escape), (LPSTR)&escape, 0, NULL );
2111}
2112
2113
2114/***********************************************************************
2115 * X11DRV_ReleaseDC (X11DRV.@)
2116 */
Maarten Lankhorst0a645952008-12-16 15:32:08 +01002117void CDECL X11DRV_ReleaseDC( HWND hwnd, HDC hdc )
Alexandre Julliard1642fbc2008-02-25 15:59:19 +01002118{
2119 struct x11drv_escape_set_drawable escape;
2120
2121 escape.code = X11DRV_SET_DRAWABLE;
2122 escape.drawable = root_window;
2123 escape.mode = IncludeInferiors;
2124 escape.drawable_rect = virtual_screen_rect;
2125 SetRect( &escape.dc_rect, 0, 0, virtual_screen_rect.right - virtual_screen_rect.left,
2126 virtual_screen_rect.bottom - virtual_screen_rect.top );
Alexandre Julliardbcf88b52010-02-16 12:37:42 +01002127 OffsetRect( &escape.dc_rect, -escape.drawable_rect.left, -escape.drawable_rect.top );
Alexandre Julliard1642fbc2008-02-25 15:59:19 +01002128 escape.fbconfig_id = 0;
2129 escape.gl_drawable = 0;
2130 escape.pixmap = 0;
2131 ExtEscape( hdc, X11DRV_ESCAPE, sizeof(escape), (LPSTR)&escape, 0, NULL );
2132}
2133
2134
Alexandre Julliarddc26f272008-03-12 15:01:24 +01002135/***********************************************************************
2136 * SetCapture (X11DRV.@)
2137 */
Maarten Lankhorst0a645952008-12-16 15:32:08 +01002138void CDECL X11DRV_SetCapture( HWND hwnd, UINT flags )
Alexandre Julliarddc26f272008-03-12 15:01:24 +01002139{
2140 struct x11drv_thread_data *thread_data = x11drv_thread_data();
2141
Alexandre Julliard06a14072008-06-26 15:08:08 +02002142 if (!thread_data) return;
Alexandre Julliard78de7e32008-03-24 17:59:40 +01002143 if (!(flags & (GUI_INMOVESIZE | GUI_INMENUMODE))) return;
Alexandre Julliarddc26f272008-03-12 15:01:24 +01002144
2145 if (hwnd)
2146 {
2147 Window grab_win = X11DRV_get_client_window( GetAncestor( hwnd, GA_ROOT ) );
2148
2149 if (!grab_win) return;
2150 wine_tsx11_lock();
2151 XFlush( gdi_display );
2152 XGrabPointer( thread_data->display, grab_win, False,
2153 PointerMotionMask | ButtonPressMask | ButtonReleaseMask,
Alexandre Julliard78de7e32008-03-24 17:59:40 +01002154 GrabModeAsync, GrabModeAsync, None, None, CurrentTime );
Alexandre Julliarddc26f272008-03-12 15:01:24 +01002155 wine_tsx11_unlock();
2156 thread_data->grab_window = grab_win;
2157 }
2158 else /* release capture */
2159 {
2160 wine_tsx11_lock();
2161 XFlush( gdi_display );
2162 XUngrabPointer( thread_data->display, CurrentTime );
Alexandre Julliard95cf00f2009-01-26 15:12:55 +01002163 XFlush( thread_data->display );
Alexandre Julliarddc26f272008-03-12 15:01:24 +01002164 wine_tsx11_unlock();
2165 thread_data->grab_window = None;
2166 }
2167}
2168
2169
Alexandre Julliard9ae0fe52001-04-24 23:28:52 +00002170/*****************************************************************
2171 * SetParent (X11DRV.@)
2172 */
Maarten Lankhorst0a645952008-12-16 15:32:08 +01002173void CDECL X11DRV_SetParent( HWND hwnd, HWND parent, HWND old_parent )
Alexandre Julliard9ae0fe52001-04-24 23:28:52 +00002174{
Alexandre Julliard43230042001-05-16 19:52:29 +00002175 Display *display = thread_display();
Pierre d'Herbemont221b0442006-12-10 23:21:28 +01002176 struct x11drv_win_data *data = X11DRV_get_win_data( hwnd );
Alexandre Julliard9ae0fe52001-04-24 23:28:52 +00002177
Pierre d'Herbemont221b0442006-12-10 23:21:28 +01002178 if (!data) return;
2179 if (parent == old_parent) return;
Alexandre Julliardfb0ff052001-10-16 21:58:58 +00002180
Pierre d'Herbemont221b0442006-12-10 23:21:28 +01002181 if (parent != GetDesktopWindow()) /* a child window */
Alexandre Julliard4d32a472005-03-25 10:38:56 +00002182 {
Pierre d'Herbemont221b0442006-12-10 23:21:28 +01002183 if (old_parent == GetDesktopWindow())
Alexandre Julliard4d32a472005-03-25 10:38:56 +00002184 {
Pierre d'Herbemont221b0442006-12-10 23:21:28 +01002185 /* destroy the old X windows */
Alexandre Julliard3b6f95c2008-03-05 16:51:09 +01002186 destroy_whole_window( display, data, FALSE );
Pierre d'Herbemont221b0442006-12-10 23:21:28 +01002187 destroy_icon_window( display, data );
2188 if (data->managed)
Alexandre Julliardf777d702005-01-31 16:34:07 +00002189 {
Pierre d'Herbemont221b0442006-12-10 23:21:28 +01002190 data->managed = FALSE;
2191 RemovePropA( data->hwnd, managed_prop );
Alexandre Julliardf777d702005-01-31 16:34:07 +00002192 }
Alexandre Julliard9ae0fe52001-04-24 23:28:52 +00002193 }
Alexandre Julliard9ae0fe52001-04-24 23:28:52 +00002194 }
Pierre d'Herbemont221b0442006-12-10 23:21:28 +01002195 else /* new top level window */
2196 {
2197 /* FIXME: we ignore errors since we can't really recover anyway */
Alexandre Julliardd147e022008-01-23 21:39:32 +01002198 create_whole_window( display, data );
Pierre d'Herbemont221b0442006-12-10 23:21:28 +01002199 }
Alexandre Julliard9ae0fe52001-04-24 23:28:52 +00002200}
2201
2202
Alexandre Julliard9ae0fe52001-04-24 23:28:52 +00002203/*****************************************************************
2204 * SetFocus (X11DRV.@)
2205 *
2206 * Set the X focus.
Alexandre Julliard9ae0fe52001-04-24 23:28:52 +00002207 */
Maarten Lankhorst0a645952008-12-16 15:32:08 +01002208void CDECL X11DRV_SetFocus( HWND hwnd )
Alexandre Julliard9ae0fe52001-04-24 23:28:52 +00002209{
Alexandre Julliard43230042001-05-16 19:52:29 +00002210 Display *display = thread_display();
Alexandre Julliardd7726c32005-02-01 18:53:59 +00002211 struct x11drv_win_data *data;
Alexandre Julliard125793d2008-02-18 17:22:51 +01002212 XWindowChanges changes;
Vincent Povirke4a50e12010-03-17 12:29:23 -05002213 DWORD timestamp;
Alexandre Julliard9ae0fe52001-04-24 23:28:52 +00002214
Alexandre Julliard9d53a1a2008-06-26 16:21:32 +02002215 if (!(hwnd = GetAncestor( hwnd, GA_ROOT ))) return;
Alexandre Julliardd7726c32005-02-01 18:53:59 +00002216 if (!(data = X11DRV_get_win_data( hwnd ))) return;
Todd Mokros88ac4b92005-08-22 09:14:21 +00002217 if (data->managed || !data->whole_window) return;
Alexandre Julliard0801ffc2001-08-24 00:26:59 +00002218
Vincent Povirke4a50e12010-03-17 12:29:23 -05002219 if (EVENT_x11_time_to_win32_time(0))
2220 /* ICCCM says don't use CurrentTime, so try to use last message time if possible */
2221 /* FIXME: this is not entirely correct */
2222 timestamp = GetMessageTime() - EVENT_x11_time_to_win32_time(0);
2223 else
2224 timestamp = CurrentTime;
2225
Alexandre Julliard0801ffc2001-08-24 00:26:59 +00002226 /* Set X focus and install colormap */
2227 wine_tsx11_lock();
Alexandre Julliard125793d2008-02-18 17:22:51 +01002228 changes.stack_mode = Above;
2229 XConfigureWindow( display, data->whole_window, CWStackMode, &changes );
Vincent Povirke4a50e12010-03-17 12:29:23 -05002230 XSetInputFocus( display, data->whole_window, RevertToParent, timestamp );
Alexandre Julliard0801ffc2001-08-24 00:26:59 +00002231 wine_tsx11_unlock();
Alexandre Julliard9ae0fe52001-04-24 23:28:52 +00002232}
2233
2234
Alexandre Julliard855308f2008-04-23 15:32:58 +02002235/***********************************************************************
Alexandre Julliard89a3bd02008-07-02 15:40:10 +02002236 * WindowPosChanging (X11DRV.@)
Alexandre Julliard855308f2008-04-23 15:32:58 +02002237 */
Maarten Lankhorst0a645952008-12-16 15:32:08 +01002238void CDECL X11DRV_WindowPosChanging( HWND hwnd, HWND insert_after, UINT swp_flags,
2239 const RECT *window_rect, const RECT *client_rect, RECT *visible_rect )
Alexandre Julliard89a3bd02008-07-02 15:40:10 +02002240{
2241 struct x11drv_win_data *data = X11DRV_get_win_data( hwnd );
2242 DWORD style = GetWindowLongW( hwnd, GWL_STYLE );
2243
2244 if (!data)
2245 {
2246 /* create the win data if the window is being made visible */
2247 if (!(style & WS_VISIBLE) && !(swp_flags & SWP_SHOWWINDOW)) return;
2248 if (!(data = X11DRV_create_win_data( hwnd ))) return;
2249 }
2250
2251 /* check if we need to switch the window to managed */
2252 if (!data->managed && data->whole_window && is_window_managed( hwnd, swp_flags, window_rect ))
2253 {
2254 TRACE( "making win %p/%lx managed\n", hwnd, data->whole_window );
2255 if (data->mapped) unmap_window( thread_display(), data );
2256 data->managed = TRUE;
2257 SetPropA( hwnd, managed_prop, (HANDLE)1 );
2258 }
2259
2260 *visible_rect = *window_rect;
2261 X11DRV_window_to_X_rect( data, visible_rect );
2262}
2263
2264
2265/***********************************************************************
2266 * WindowPosChanged (X11DRV.@)
2267 */
Maarten Lankhorst0a645952008-12-16 15:32:08 +01002268void CDECL X11DRV_WindowPosChanged( HWND hwnd, HWND insert_after, UINT swp_flags,
2269 const RECT *rectWindow, const RECT *rectClient,
2270 const RECT *visible_rect, const RECT *valid_rects )
Alexandre Julliard855308f2008-04-23 15:32:58 +02002271{
Alexandre Julliarde7044cb2008-06-26 16:47:42 +02002272 struct x11drv_thread_data *thread_data;
2273 Display *display;
Alexandre Julliard855308f2008-04-23 15:32:58 +02002274 struct x11drv_win_data *data = X11DRV_get_win_data( hwnd );
2275 DWORD new_style = GetWindowLongW( hwnd, GWL_STYLE );
Alexandre Julliard08b83252010-02-08 17:14:01 +01002276 RECT old_window_rect, old_whole_rect, old_client_rect;
Alexandre Julliard855308f2008-04-23 15:32:58 +02002277 int event_type;
2278
Alexandre Julliard89a3bd02008-07-02 15:40:10 +02002279 if (!data) return;
Alexandre Julliard855308f2008-04-23 15:32:58 +02002280
Alexandre Julliarde7044cb2008-06-26 16:47:42 +02002281 thread_data = x11drv_thread_data();
2282 display = thread_data->display;
2283
Alexandre Julliard08b83252010-02-08 17:14:01 +01002284 old_window_rect = data->window_rect;
Alexandre Julliard855308f2008-04-23 15:32:58 +02002285 old_whole_rect = data->whole_rect;
2286 old_client_rect = data->client_rect;
2287 data->window_rect = *rectWindow;
Alexandre Julliard89a3bd02008-07-02 15:40:10 +02002288 data->whole_rect = *visible_rect;
Alexandre Julliard855308f2008-04-23 15:32:58 +02002289 data->client_rect = *rectClient;
Alexandre Julliard855308f2008-04-23 15:32:58 +02002290
2291 TRACE( "win %p window %s client %s style %08x flags %08x\n",
2292 hwnd, wine_dbgstr_rect(rectWindow), wine_dbgstr_rect(rectClient), new_style, swp_flags );
2293
2294 if (!IsRectEmpty( &valid_rects[0] ))
2295 {
2296 int x_offset = old_whole_rect.left - data->whole_rect.left;
2297 int y_offset = old_whole_rect.top - data->whole_rect.top;
2298
2299 /* if all that happened is that the whole window moved, copy everything */
2300 if (!(swp_flags & SWP_FRAMECHANGED) &&
2301 old_whole_rect.right - data->whole_rect.right == x_offset &&
2302 old_whole_rect.bottom - data->whole_rect.bottom == y_offset &&
2303 old_client_rect.left - data->client_rect.left == x_offset &&
2304 old_client_rect.right - data->client_rect.right == x_offset &&
2305 old_client_rect.top - data->client_rect.top == y_offset &&
2306 old_client_rect.bottom - data->client_rect.bottom == y_offset &&
2307 !memcmp( &valid_rects[0], &data->client_rect, sizeof(RECT) ))
2308 {
2309 /* if we have an X window the bits will be moved by the X server */
2310 if (!data->whole_window)
2311 move_window_bits( data, &old_whole_rect, &data->whole_rect, &old_client_rect );
2312 }
2313 else
2314 move_window_bits( data, &valid_rects[1], &valid_rects[0], &old_client_rect );
2315 }
2316
2317 wine_tsx11_lock();
2318 XFlush( gdi_display ); /* make sure painting is done before we move the window */
2319 wine_tsx11_unlock();
2320
2321 sync_client_position( display, data, swp_flags, &old_client_rect, &old_whole_rect );
2322
2323 if (!data->whole_window) return;
2324
2325 /* check if we are currently processing an event relevant to this window */
2326 event_type = 0;
2327 if (thread_data->current_event && thread_data->current_event->xany.window == data->whole_window)
2328 event_type = thread_data->current_event->type;
2329
2330 if (event_type != ConfigureNotify && event_type != PropertyNotify)
2331 event_type = 0; /* ignore other events */
2332
Alexandre Julliard6b9517a2008-05-01 17:45:17 +02002333 if (data->mapped)
2334 {
2335 if (((swp_flags & SWP_HIDEWINDOW) && !(new_style & WS_VISIBLE)) ||
Alexandre Julliard2cf9cdd2010-05-24 16:41:20 +02002336 (event_type != ConfigureNotify && !is_window_rect_mapped( rectWindow )))
Alexandre Julliard6b9517a2008-05-01 17:45:17 +02002337 unmap_window( display, data );
2338 }
Alexandre Julliard855308f2008-04-23 15:32:58 +02002339
2340 /* don't change position if we are about to minimize or maximize a managed window */
2341 if (!event_type &&
2342 !(data->managed && (swp_flags & SWP_STATECHANGED) && (new_style & (WS_MINIMIZE|WS_MAXIMIZE))))
Alexandre Julliard08b83252010-02-08 17:14:01 +01002343 sync_window_position( display, data, swp_flags,
2344 &old_window_rect, &old_whole_rect, &old_client_rect );
Alexandre Julliard855308f2008-04-23 15:32:58 +02002345
2346 if ((new_style & WS_VISIBLE) &&
2347 ((new_style & WS_MINIMIZE) || is_window_rect_mapped( rectWindow )))
2348 {
2349 if (!data->mapped || (swp_flags & (SWP_FRAMECHANGED|SWP_STATECHANGED)))
2350 set_wm_hints( display, data );
2351
2352 if (!data->mapped)
2353 {
2354 map_window( display, data, new_style );
2355 }
2356 else if ((swp_flags & SWP_STATECHANGED) && (!data->iconic != !(new_style & WS_MINIMIZE)))
2357 {
2358 data->iconic = (new_style & WS_MINIMIZE) != 0;
2359 TRACE( "changing win %p iconic state to %u\n", data->hwnd, data->iconic );
2360 wine_tsx11_lock();
2361 if (data->iconic)
2362 XIconifyWindow( display, data->whole_window, DefaultScreen(display) );
2363 else if (is_window_rect_mapped( rectWindow ))
2364 XMapWindow( display, data->whole_window );
2365 wine_tsx11_unlock();
2366 update_net_wm_states( display, data );
2367 }
2368 else if (!event_type)
2369 {
2370 update_net_wm_states( display, data );
2371 }
2372 }
2373
2374 wine_tsx11_lock();
2375 XFlush( display ); /* make sure changes are done before we start painting again */
2376 wine_tsx11_unlock();
2377}
2378
2379
Alexandre Julliard31b40612008-07-31 11:40:49 +02002380/***********************************************************************
2381 * ShowWindow (X11DRV.@)
2382 */
Maarten Lankhorst0a645952008-12-16 15:32:08 +01002383UINT CDECL X11DRV_ShowWindow( HWND hwnd, INT cmd, RECT *rect, UINT swp )
Alexandre Julliard31b40612008-07-31 11:40:49 +02002384{
2385 int x, y;
2386 unsigned int width, height, border, depth;
2387 Window root, top;
2388 DWORD style = GetWindowLongW( hwnd, GWL_STYLE );
2389 struct x11drv_thread_data *thread_data = x11drv_thread_data();
2390 struct x11drv_win_data *data = X11DRV_get_win_data( hwnd );
2391
2392 if (!data || !data->whole_window || !data->managed || !data->mapped || data->iconic) return swp;
2393 if (style & WS_MINIMIZE) return swp;
Alexandre Julliard3cb23d32008-09-17 21:13:11 +02002394 if (IsRectEmpty( rect )) return swp;
Alexandre Julliard31b40612008-07-31 11:40:49 +02002395
2396 /* only fetch the new rectangle if the ShowWindow was a result of a window manager event */
2397
2398 if (!thread_data->current_event || thread_data->current_event->xany.window != data->whole_window)
2399 return swp;
2400
2401 if (thread_data->current_event->type != ConfigureNotify &&
2402 thread_data->current_event->type != PropertyNotify)
2403 return swp;
2404
2405 TRACE( "win %p/%lx cmd %d at %s flags %08x\n",
2406 hwnd, data->whole_window, cmd, wine_dbgstr_rect(rect), swp );
2407
2408 wine_tsx11_lock();
2409 XGetGeometry( thread_data->display, data->whole_window,
2410 &root, &x, &y, &width, &height, &border, &depth );
2411 XTranslateCoordinates( thread_data->display, data->whole_window, root, 0, 0, &x, &y, &top );
2412 wine_tsx11_unlock();
2413 rect->left = x;
2414 rect->top = y;
2415 rect->right = x + width;
2416 rect->bottom = y + height;
2417 OffsetRect( rect, virtual_screen_rect.left, virtual_screen_rect.top );
2418 X11DRV_X_to_window_rect( data, rect );
2419 return swp & ~(SWP_NOMOVE | SWP_NOCLIENTMOVE | SWP_NOSIZE | SWP_NOCLIENTSIZE);
2420}
2421
2422
Alexandre Julliard9ae0fe52001-04-24 23:28:52 +00002423/**********************************************************************
Patrik Stridvall01d5e5b2001-07-02 19:59:40 +00002424 * SetWindowIcon (X11DRV.@)
Alexandre Julliard9ae0fe52001-04-24 23:28:52 +00002425 *
2426 * hIcon or hIconSm has changed (or is being initialised for the
2427 * first time). Complete the X11 driver-specific initialisation
2428 * and set the window hints.
2429 *
2430 * This is not entirely correct, may need to create
2431 * an icon window and set the pixmap as a background
2432 */
Maarten Lankhorst0a645952008-12-16 15:32:08 +01002433void CDECL X11DRV_SetWindowIcon( HWND hwnd, UINT type, HICON icon )
Alexandre Julliard9ae0fe52001-04-24 23:28:52 +00002434{
Alexandre Julliard43230042001-05-16 19:52:29 +00002435 Display *display = thread_display();
Alexandre Julliardfc5ce142005-01-17 19:17:47 +00002436 struct x11drv_win_data *data;
Alexandre Julliard9ae0fe52001-04-24 23:28:52 +00002437
Alexandre Julliard9ae0fe52001-04-24 23:28:52 +00002438
Alexandre Julliardfc5ce142005-01-17 19:17:47 +00002439 if (!(data = X11DRV_get_win_data( hwnd ))) return;
Alexandre Julliardf777d702005-01-31 16:34:07 +00002440 if (!data->whole_window) return;
Alexandre Julliardd7726c32005-02-01 18:53:59 +00002441 if (!data->managed) return;
Alexandre Julliard8fd26b92001-10-15 17:56:45 +00002442
Alexandre Julliardbde89572007-08-16 23:27:37 +02002443 if (data->wm_hints)
Alexandre Julliard9ae0fe52001-04-24 23:28:52 +00002444 {
Alexandre Julliarda551dfe2010-04-19 17:51:44 +02002445 if (type == ICON_BIG) set_icon_hints( display, data, icon, 0 );
2446 else set_icon_hints( display, data, 0, icon );
Alexandre Julliarde9119c12002-09-24 18:36:51 +00002447 wine_tsx11_lock();
Alexandre Julliardbde89572007-08-16 23:27:37 +02002448 XSetWMHints( display, data->whole_window, data->wm_hints );
Alexandre Julliarde9119c12002-09-24 18:36:51 +00002449 wine_tsx11_unlock();
Alexandre Julliard9ae0fe52001-04-24 23:28:52 +00002450 }
Alexandre Julliard9ae0fe52001-04-24 23:28:52 +00002451}
Alexandre Julliard395928d2008-01-23 16:30:18 +01002452
2453
2454/***********************************************************************
2455 * SetWindowRgn (X11DRV.@)
2456 *
2457 * Assign specified region to window (for non-rectangular windows)
2458 */
Maarten Lankhorst0a645952008-12-16 15:32:08 +01002459int CDECL X11DRV_SetWindowRgn( HWND hwnd, HRGN hrgn, BOOL redraw )
Alexandre Julliard395928d2008-01-23 16:30:18 +01002460{
2461 struct x11drv_win_data *data;
2462
2463 if ((data = X11DRV_get_win_data( hwnd )))
2464 {
2465 sync_window_region( thread_display(), data, hrgn );
Alexandre Julliard395928d2008-01-23 16:30:18 +01002466 }
Alexandre Julliard9d45cfd2008-09-08 15:51:08 +02002467 else if (X11DRV_get_whole_window( hwnd ))
Alexandre Julliard395928d2008-01-23 16:30:18 +01002468 {
Alexandre Julliard9d45cfd2008-09-08 15:51:08 +02002469 SendMessageW( hwnd, WM_X11DRV_SET_WIN_REGION, 0, 0 );
Alexandre Julliard395928d2008-01-23 16:30:18 +01002470 }
Alexandre Julliard395928d2008-01-23 16:30:18 +01002471 return TRUE;
2472}
Alexandre Julliard24dbaa02008-04-17 16:13:34 +02002473
2474
Alexandre Julliardbe3c3a52008-09-12 15:54:02 +02002475/***********************************************************************
2476 * SetLayeredWindowAttributes (X11DRV.@)
2477 *
2478 * Set transparency attributes for a layered window.
2479 */
Maarten Lankhorst0a645952008-12-16 15:32:08 +01002480void CDECL X11DRV_SetLayeredWindowAttributes( HWND hwnd, COLORREF key, BYTE alpha, DWORD flags )
Alexandre Julliardbe3c3a52008-09-12 15:54:02 +02002481{
Alexandre Julliardfb84ba52008-09-22 12:52:53 +02002482 struct x11drv_win_data *data = X11DRV_get_win_data( hwnd );
Alexandre Julliardbe3c3a52008-09-12 15:54:02 +02002483
Alexandre Julliardfb84ba52008-09-22 12:52:53 +02002484 if (data)
2485 {
2486 if (data->whole_window)
2487 sync_window_opacity( thread_display(), data->whole_window, key, alpha, flags );
2488 }
2489 else
2490 {
2491 Window win = X11DRV_get_whole_window( hwnd );
2492 if (win) sync_window_opacity( gdi_display, win, key, alpha, flags );
2493 }
Alexandre Julliardbe3c3a52008-09-12 15:54:02 +02002494}
2495
2496
Alexandre Julliard370368a2008-09-08 15:42:24 +02002497/**********************************************************************
2498 * X11DRV_WindowMessage (X11DRV.@)
2499 */
Maarten Lankhorst0a645952008-12-16 15:32:08 +01002500LRESULT CDECL X11DRV_WindowMessage( HWND hwnd, UINT msg, WPARAM wp, LPARAM lp )
Alexandre Julliard370368a2008-09-08 15:42:24 +02002501{
Alexandre Julliard9d45cfd2008-09-08 15:51:08 +02002502 struct x11drv_win_data *data;
2503
Alexandre Julliard370368a2008-09-08 15:42:24 +02002504 switch(msg)
2505 {
2506 case WM_X11DRV_ACQUIRE_SELECTION:
2507 return X11DRV_AcquireClipboard( hwnd );
Alexandre Julliard370368a2008-09-08 15:42:24 +02002508 case WM_X11DRV_SET_WIN_FORMAT:
2509 return set_win_format( hwnd, (XID)wp );
Alexandre Julliard9d45cfd2008-09-08 15:51:08 +02002510 case WM_X11DRV_SET_WIN_REGION:
2511 if ((data = X11DRV_get_win_data( hwnd ))) sync_window_region( thread_display(), data, (HRGN)1 );
2512 return 0;
Alexandre Julliard370368a2008-09-08 15:42:24 +02002513 case WM_X11DRV_RESIZE_DESKTOP:
2514 X11DRV_resize_desktop( LOWORD(lp), HIWORD(lp) );
2515 return 0;
Alexandre Julliard65515532010-04-28 19:23:05 -05002516 case WM_X11DRV_SET_CURSOR:
2517 set_window_cursor( hwnd, (HCURSOR)lp );
2518 return 0;
Alexandre Julliard370368a2008-09-08 15:42:24 +02002519 default:
2520 FIXME( "got window msg %x hwnd %p wp %lx lp %lx\n", msg, hwnd, wp, lp );
2521 return 0;
2522 }
2523}
2524
2525
Alexandre Julliard24dbaa02008-04-17 16:13:34 +02002526/***********************************************************************
2527 * is_netwm_supported
2528 */
2529static BOOL is_netwm_supported( Display *display, Atom atom )
2530{
2531 static Atom *net_supported;
2532 static int net_supported_count = -1;
2533 int i;
2534
2535 wine_tsx11_lock();
2536 if (net_supported_count == -1)
2537 {
2538 Atom type;
2539 int format;
2540 unsigned long count, remaining;
2541
2542 if (!XGetWindowProperty( display, DefaultRootWindow(display), x11drv_atom(_NET_SUPPORTED), 0,
2543 ~0UL, False, XA_ATOM, &type, &format, &count,
2544 &remaining, (unsigned char **)&net_supported ))
2545 net_supported_count = get_property_size( format, count ) / sizeof(Atom);
2546 else
2547 net_supported_count = 0;
2548 }
2549 wine_tsx11_unlock();
2550
2551 for (i = 0; i < net_supported_count; i++)
2552 if (net_supported[i] == atom) return TRUE;
2553 return FALSE;
2554}
2555
2556
2557/***********************************************************************
2558 * SysCommand (X11DRV.@)
2559 *
2560 * Perform WM_SYSCOMMAND handling.
2561 */
Maarten Lankhorst0a645952008-12-16 15:32:08 +01002562LRESULT CDECL X11DRV_SysCommand( HWND hwnd, WPARAM wparam, LPARAM lparam )
Alexandre Julliard24dbaa02008-04-17 16:13:34 +02002563{
2564 WPARAM hittest = wparam & 0x0f;
2565 DWORD dwPoint;
2566 int x, y, dir;
2567 XEvent xev;
2568 Display *display = thread_display();
2569 struct x11drv_win_data *data;
2570
2571 if (!(data = X11DRV_get_win_data( hwnd ))) return -1;
2572 if (!data->whole_window || !data->managed || !data->mapped) return -1;
2573
2574 switch (wparam & 0xfff0)
2575 {
2576 case SC_MOVE:
2577 if (!hittest) dir = _NET_WM_MOVERESIZE_MOVE_KEYBOARD;
2578 else dir = _NET_WM_MOVERESIZE_MOVE;
2579 break;
2580 case SC_SIZE:
2581 /* windows without WS_THICKFRAME are not resizable through the window manager */
2582 if (!(GetWindowLongW( hwnd, GWL_STYLE ) & WS_THICKFRAME)) return -1;
2583
2584 switch (hittest)
2585 {
2586 case WMSZ_LEFT: dir = _NET_WM_MOVERESIZE_SIZE_LEFT; break;
2587 case WMSZ_RIGHT: dir = _NET_WM_MOVERESIZE_SIZE_RIGHT; break;
2588 case WMSZ_TOP: dir = _NET_WM_MOVERESIZE_SIZE_TOP; break;
2589 case WMSZ_TOPLEFT: dir = _NET_WM_MOVERESIZE_SIZE_TOPLEFT; break;
2590 case WMSZ_TOPRIGHT: dir = _NET_WM_MOVERESIZE_SIZE_TOPRIGHT; break;
2591 case WMSZ_BOTTOM: dir = _NET_WM_MOVERESIZE_SIZE_BOTTOM; break;
2592 case WMSZ_BOTTOMLEFT: dir = _NET_WM_MOVERESIZE_SIZE_BOTTOMLEFT; break;
2593 case WMSZ_BOTTOMRIGHT: dir = _NET_WM_MOVERESIZE_SIZE_BOTTOMRIGHT; break;
2594 default: dir = _NET_WM_MOVERESIZE_SIZE_KEYBOARD; break;
2595 }
2596 break;
2597
2598 case SC_KEYMENU:
2599 /* prevent a simple ALT press+release from activating the system menu,
2600 * as that can get confusing on managed windows */
2601 if ((WCHAR)lparam) return -1; /* got an explicit char */
2602 if (GetMenu( hwnd )) return -1; /* window has a real menu */
2603 if (!(GetWindowLongW( hwnd, GWL_STYLE ) & WS_SYSMENU)) return -1; /* no system menu */
2604 TRACE( "ignoring SC_KEYMENU wp %lx lp %lx\n", wparam, lparam );
2605 return 0;
2606
2607 default:
2608 return -1;
2609 }
2610
2611 if (IsZoomed(hwnd)) return -1;
2612
2613 if (!is_netwm_supported( display, x11drv_atom(_NET_WM_MOVERESIZE) ))
2614 {
2615 TRACE( "_NET_WM_MOVERESIZE not supported\n" );
2616 return -1;
2617 }
2618
2619 dwPoint = GetMessagePos();
2620 x = (short)LOWORD(dwPoint);
2621 y = (short)HIWORD(dwPoint);
2622
2623 TRACE("hwnd %p, x %d, y %d, dir %d\n", hwnd, x, y, dir);
2624
2625 xev.xclient.type = ClientMessage;
2626 xev.xclient.window = X11DRV_get_whole_window(hwnd);
2627 xev.xclient.message_type = x11drv_atom(_NET_WM_MOVERESIZE);
2628 xev.xclient.serial = 0;
2629 xev.xclient.display = display;
2630 xev.xclient.send_event = True;
2631 xev.xclient.format = 32;
Alexandre Julliard9fab7b42008-09-12 11:03:26 +02002632 xev.xclient.data.l[0] = x - virtual_screen_rect.left; /* x coord */
2633 xev.xclient.data.l[1] = y - virtual_screen_rect.top; /* y coord */
Alexandre Julliard24dbaa02008-04-17 16:13:34 +02002634 xev.xclient.data.l[2] = dir; /* direction */
2635 xev.xclient.data.l[3] = 1; /* button */
2636 xev.xclient.data.l[4] = 0; /* unused */
2637
2638 /* need to ungrab the pointer that may have been automatically grabbed
2639 * with a ButtonPress event */
2640 wine_tsx11_lock();
2641 XUngrabPointer( display, CurrentTime );
2642 XSendEvent(display, root_window, False, SubstructureNotifyMask, &xev);
2643 wine_tsx11_unlock();
2644 return 0;
2645}