Delay the creation of the X atoms until we really need them, to allow
[wine] / dlls / x11drv / window.c
1 /*
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
7  *
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
20  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
21  */
22
23 #include "config.h"
24
25 #include <stdarg.h>
26 #include <stdlib.h>
27 #ifdef HAVE_UNISTD_H
28 # include <unistd.h>
29 #endif
30
31 #include "ts_xlib.h"
32 #include <X11/Xresource.h>
33 #include <X11/Xutil.h>
34
35 #include "windef.h"
36 #include "winbase.h"
37 #include "wingdi.h"
38 #include "winreg.h"
39 #include "winuser.h"
40 #include "wine/unicode.h"
41
42 #include "wine/debug.h"
43 #include "x11drv.h"
44 #include "win.h"
45 #include "winpos.h"
46 #include "mwm.h"
47
48 WINE_DEFAULT_DEBUG_CHANNEL(x11drv);
49
50 extern Pixmap X11DRV_BITMAP_Pixmap( HBITMAP );
51
52 #define HAS_DLGFRAME(style,exStyle) \
53     (((exStyle) & WS_EX_DLGMODALFRAME) || \
54      (((style) & WS_DLGFRAME) && !((style) & WS_THICKFRAME)))
55
56 /* X context to associate a hwnd to an X window */
57 XContext winContext = 0;
58
59 Atom X11DRV_Atoms[NB_XATOMS - FIRST_XATOM];
60
61 static const char * const atom_names[NB_XATOMS - FIRST_XATOM] =
62 {
63     "CLIPBOARD",
64     "COMPOUND_TEXT",
65     "MULTIPLE",
66     "SELECTION_DATA",
67     "TARGETS",
68     "TEXT",
69     "UTF8_STRING",
70     "RAW_ASCENT",
71     "RAW_DESCENT",
72     "RAW_CAP_HEIGHT",
73     "WM_PROTOCOLS",
74     "WM_DELETE_WINDOW",
75     "WM_TAKE_FOCUS",
76     "KWM_DOCKWINDOW",
77     "DndProtocol",
78     "DndSelection",
79     "_MOTIF_WM_HINTS",
80     "_KDE_NET_WM_SYSTEM_TRAY_WINDOW_FOR",
81     "_NET_WM_PID",
82     "_NET_WM_PING",
83     "_NET_WM_NAME",
84     "XdndAware",
85     "XdndEnter",
86     "XdndPosition",
87     "XdndStatus",
88     "XdndLeave",
89     "XdndFinished",
90     "XdndDrop",
91     "XdndActionCopy",
92     "XdndActionMove",
93     "XdndActionLink",
94     "XdndActionAsk",
95     "XdndActionPrivate",
96     "XdndSelection",
97     "XdndTarget",
98     "XdndTypeList",
99     "image/gif",
100     "text/html",
101     "text/plain",
102     "text/rtf",
103     "text/richtext"
104 };
105
106 static LPCSTR whole_window_atom;
107 static LPCSTR client_window_atom;
108 static LPCSTR icon_window_atom;
109
110 /***********************************************************************
111  *              is_window_managed
112  *
113  * Check if a given window should be managed
114  */
115 inline static BOOL is_window_managed( WND *win )
116 {
117     if (!managed_mode) return FALSE;
118     /* tray window is always managed */
119     if (win->dwExStyle & WS_EX_TRAYWINDOW) return TRUE;
120     /* child windows are not managed */
121     if (win->dwStyle & WS_CHILD) return FALSE;
122     /* tool windows are not managed */
123     if (win->dwExStyle & WS_EX_TOOLWINDOW) return FALSE;
124     /* windows with caption or thick frame are managed */
125     if ((win->dwStyle & WS_CAPTION) == WS_CAPTION) return TRUE;
126     if (win->dwStyle & WS_THICKFRAME) return TRUE;
127     /* default: not managed */
128     return FALSE;
129 }
130
131
132 /***********************************************************************
133  *              is_client_window_mapped
134  *
135  * Check if the X client window should be mapped
136  */
137 inline static BOOL is_client_window_mapped( WND *win )
138 {
139     struct x11drv_win_data *data = win->pDriverData;
140     return !(win->dwStyle & WS_MINIMIZE) && !IsRectEmpty( &data->client_rect );
141 }
142
143
144 /***********************************************************************
145  *              get_window_attributes
146  *
147  * Fill the window attributes structure for an X window.
148  */
149 static int get_window_attributes( Display *display, WND *win, XSetWindowAttributes *attr )
150 {
151     BOOL is_top_level = is_window_top_level( win );
152     BOOL managed = is_top_level && is_window_managed( win );
153
154     if (managed) WIN_SetExStyle( win->hwndSelf, win->dwExStyle | WS_EX_MANAGED );
155     else WIN_SetExStyle( win->hwndSelf, win->dwExStyle & ~WS_EX_MANAGED );
156
157     attr->override_redirect = !managed;
158     attr->colormap          = X11DRV_PALETTE_PaletteXColormap;
159     attr->save_under        = ((win->clsStyle & CS_SAVEBITS) != 0);
160     attr->cursor            = x11drv_thread_data()->cursor;
161     attr->event_mask        = (ExposureMask | PointerMotionMask |
162                                ButtonPressMask | ButtonReleaseMask | EnterWindowMask);
163
164     if (is_window_top_level( win ))
165         attr->event_mask |= (KeyPressMask | KeyReleaseMask | StructureNotifyMask |
166                              FocusChangeMask | KeymapStateMask);
167
168     return (CWOverrideRedirect | CWSaveUnder | CWEventMask | CWColormap | CWCursor);
169 }
170
171
172 /***********************************************************************
173  *              X11DRV_sync_window_style
174  *
175  * Change the X window attributes when the window style has changed.
176  */
177 void X11DRV_sync_window_style( Display *display, WND *win )
178 {
179     XSetWindowAttributes attr;
180     int mask;
181
182     wine_tsx11_lock();
183     mask = get_window_attributes( display, win, &attr );
184     XChangeWindowAttributes( display, get_whole_window(win), mask, &attr );
185     wine_tsx11_unlock();
186 }
187
188
189 /***********************************************************************
190  *              get_window_changes
191  *
192  * fill the window changes structure
193  */
194 static int get_window_changes( XWindowChanges *changes, const RECT *old, const RECT *new )
195 {
196     int mask = 0;
197
198     if (old->right - old->left != new->right - new->left )
199     {
200         if (!(changes->width = new->right - new->left)) changes->width = 1;
201         mask |= CWWidth;
202     }
203     if (old->bottom - old->top != new->bottom - new->top)
204     {
205         if (!(changes->height = new->bottom - new->top)) changes->height = 1;
206         mask |= CWHeight;
207     }
208     if (old->left != new->left)
209     {
210         changes->x = new->left;
211         mask |= CWX;
212     }
213     if (old->top != new->top)
214     {
215         changes->y = new->top;
216         mask |= CWY;
217     }
218     return mask;
219 }
220
221
222 /***********************************************************************
223  *              create_icon_window
224  */
225 static Window create_icon_window( Display *display, WND *win )
226 {
227     struct x11drv_win_data *data = win->pDriverData;
228     XSetWindowAttributes attr;
229
230     attr.event_mask = (ExposureMask | KeyPressMask | KeyReleaseMask | PointerMotionMask |
231                        ButtonPressMask | ButtonReleaseMask | EnterWindowMask);
232     attr.bit_gravity = NorthWestGravity;
233     attr.backing_store = NotUseful/*WhenMapped*/;
234     attr.colormap      = X11DRV_PALETTE_PaletteXColormap; /* Needed due to our visual */
235
236     wine_tsx11_lock();
237     data->icon_window = XCreateWindow( display, root_window, 0, 0,
238                                        GetSystemMetrics( SM_CXICON ),
239                                        GetSystemMetrics( SM_CYICON ),
240                                        0, screen_depth,
241                                        InputOutput, visual,
242                                        CWEventMask | CWBitGravity | CWBackingStore | CWColormap, &attr );
243     XSaveContext( display, data->icon_window, winContext, (char *)win->hwndSelf );
244     wine_tsx11_unlock();
245
246     TRACE( "created %lx\n", data->icon_window );
247     SetPropA( win->hwndSelf, icon_window_atom, (HANDLE)data->icon_window );
248     return data->icon_window;
249 }
250
251
252
253 /***********************************************************************
254  *              destroy_icon_window
255  */
256 inline static void destroy_icon_window( Display *display, WND *win )
257 {
258     struct x11drv_win_data *data = win->pDriverData;
259
260     if (!data->icon_window) return;
261     if (x11drv_thread_data()->cursor_window == data->icon_window)
262         x11drv_thread_data()->cursor_window = None;
263     wine_tsx11_lock();
264     XDeleteContext( display, data->icon_window, winContext );
265     XDestroyWindow( display, data->icon_window );
266     data->icon_window = 0;
267     wine_tsx11_unlock();
268     RemovePropA( win->hwndSelf, icon_window_atom );
269 }
270
271
272 /***********************************************************************
273  *              set_icon_hints
274  *
275  * Set the icon wm hints
276  */
277 static void set_icon_hints( Display *display, WND *wndPtr, XWMHints *hints )
278 {
279     X11DRV_WND_DATA *data = wndPtr->pDriverData;
280     HICON hIcon = (HICON)GetClassLongA( wndPtr->hwndSelf, GCL_HICON );
281
282     if (data->hWMIconBitmap) DeleteObject( data->hWMIconBitmap );
283     if (data->hWMIconMask) DeleteObject( data->hWMIconMask);
284     data->hWMIconBitmap = 0;
285     data->hWMIconMask = 0;
286
287     if (!(wndPtr->dwExStyle & WS_EX_MANAGED))
288     {
289         destroy_icon_window( display, wndPtr );
290         hints->flags &= ~(IconPixmapHint | IconMaskHint | IconWindowHint);
291     }
292     else if (!hIcon)
293     {
294         if (!data->icon_window) create_icon_window( display, wndPtr );
295         hints->icon_window = data->icon_window;
296         hints->flags = (hints->flags & ~(IconPixmapHint | IconMaskHint)) | IconWindowHint;
297     }
298     else
299     {
300         HBITMAP hbmOrig;
301         RECT rcMask;
302         BITMAP bmMask;
303         ICONINFO ii;
304         HDC hDC;
305
306         GetIconInfo(hIcon, &ii);
307
308         GetObjectA(ii.hbmMask, sizeof(bmMask), &bmMask);
309         rcMask.top    = 0;
310         rcMask.left   = 0;
311         rcMask.right  = bmMask.bmWidth;
312         rcMask.bottom = bmMask.bmHeight;
313
314         hDC = CreateCompatibleDC(0);
315         hbmOrig = SelectObject(hDC, ii.hbmMask);
316         InvertRect(hDC, &rcMask);
317         SelectObject(hDC, ii.hbmColor);  /* force the color bitmap to x11drv mode too */
318         SelectObject(hDC, hbmOrig);
319         DeleteDC(hDC);
320
321         data->hWMIconBitmap = ii.hbmColor;
322         data->hWMIconMask = ii.hbmMask;
323
324         hints->icon_pixmap = X11DRV_BITMAP_Pixmap(data->hWMIconBitmap);
325         hints->icon_mask = X11DRV_BITMAP_Pixmap(data->hWMIconMask);
326         destroy_icon_window( display, wndPtr );
327         hints->flags = (hints->flags & ~IconWindowHint) | IconPixmapHint | IconMaskHint;
328     }
329 }
330
331
332 /***********************************************************************
333  *              set_size_hints
334  *
335  * set the window size hints
336  */
337 static void set_size_hints( Display *display, WND *win )
338 {
339     XSizeHints* size_hints;
340     struct x11drv_win_data *data = win->pDriverData;
341
342     if ((size_hints = XAllocSizeHints()))
343     {
344         size_hints->win_gravity = StaticGravity;
345         size_hints->x = data->whole_rect.left;
346         size_hints->y = data->whole_rect.top;
347         size_hints->flags = PWinGravity | PPosition;
348
349         if (HAS_DLGFRAME( win->dwStyle, win->dwExStyle ))
350         {
351             size_hints->max_width = data->whole_rect.right - data->whole_rect.left;
352             size_hints->max_height = data->whole_rect.bottom - data->whole_rect.top;
353             size_hints->min_width = size_hints->max_width;
354             size_hints->min_height = size_hints->max_height;
355             size_hints->flags |= PMinSize | PMaxSize;
356         }
357         XSetWMNormalHints( display, data->whole_window, size_hints );
358         XFree( size_hints );
359     }
360 }
361
362
363 /***********************************************************************
364  *              X11DRV_set_wm_hints
365  *
366  * Set the window manager hints for a newly-created window
367  */
368 void X11DRV_set_wm_hints( Display *display, WND *win )
369 {
370     struct x11drv_win_data *data = win->pDriverData;
371     Window group_leader;
372     XClassHint *class_hints;
373     XWMHints* wm_hints;
374     Atom protocols[3];
375     MwmHints mwm_hints;
376     Atom dndVersion = 4;
377     int i;
378
379     wine_tsx11_lock();
380
381     /* wm protocols */
382     i = 0;
383     protocols[i++] = x11drv_atom(WM_DELETE_WINDOW);
384     protocols[i++] = x11drv_atom(_NET_WM_PING);
385     if (use_take_focus) protocols[i++] = x11drv_atom(WM_TAKE_FOCUS);
386     XChangeProperty( display, data->whole_window, x11drv_atom(WM_PROTOCOLS),
387                      XA_ATOM, 32, PropModeReplace, (char *)protocols, i );
388
389     /* class hints */
390     if ((class_hints = XAllocClassHint()))
391     {
392         class_hints->res_name = "wine";
393         class_hints->res_class = "Wine";
394         XSetClassHint( display, data->whole_window, class_hints );
395         XFree( class_hints );
396     }
397
398     /* transient for hint */
399     if (win->owner)
400     {
401         Window owner_win = X11DRV_get_whole_window( win->owner );
402         XSetTransientForHint( display, data->whole_window, owner_win );
403         group_leader = owner_win;
404     }
405     else group_leader = data->whole_window;
406
407     /* size hints */
408     set_size_hints( display, win );
409
410     /* systray properties (KDE only for now) */
411     if (win->dwExStyle & WS_EX_TRAYWINDOW)
412     {
413         int val = 1;
414         XChangeProperty( display, data->whole_window, x11drv_atom(KWM_DOCKWINDOW),
415                          x11drv_atom(KWM_DOCKWINDOW), 32, PropModeReplace, (char*)&val, 1 );
416         XChangeProperty( display, data->whole_window, x11drv_atom(_KDE_NET_WM_SYSTEM_TRAY_WINDOW_FOR),
417                          XA_WINDOW, 32, PropModeReplace, (char*)&data->whole_window, 1 );
418     }
419
420     /* set the WM_CLIENT_MACHINE and WM_LOCALE_NAME properties */
421     XSetWMProperties(display, data->whole_window, NULL, NULL, NULL, 0, NULL, NULL, NULL);
422     /* set the pid. together, these properties are needed so the window manager can kill us if we freeze */
423     i = getpid();
424     XChangeProperty(display, data->whole_window, x11drv_atom(_NET_WM_PID),
425                     XA_CARDINAL, 32, PropModeReplace, (char *)&i, 1);
426
427     mwm_hints.flags = MWM_HINTS_FUNCTIONS | MWM_HINTS_DECORATIONS;
428     mwm_hints.functions = 0;
429     if ((win->dwStyle & WS_CAPTION) == WS_CAPTION) mwm_hints.functions |= MWM_FUNC_MOVE;
430     if (win->dwStyle & WS_THICKFRAME) mwm_hints.functions |= MWM_FUNC_MOVE | MWM_FUNC_RESIZE;
431     if (win->dwStyle & WS_MINIMIZEBOX) mwm_hints.functions |= MWM_FUNC_MINIMIZE;
432     if (win->dwStyle & WS_MAXIMIZEBOX) mwm_hints.functions |= MWM_FUNC_MAXIMIZE;
433     if (win->dwStyle & WS_SYSMENU)    mwm_hints.functions |= MWM_FUNC_CLOSE;
434     mwm_hints.decorations = 0;
435     if ((win->dwStyle & WS_CAPTION) == WS_CAPTION) mwm_hints.decorations |= MWM_DECOR_TITLE;
436     if (win->dwExStyle & WS_EX_DLGMODALFRAME) mwm_hints.decorations |= MWM_DECOR_BORDER;
437     else if (win->dwStyle & WS_THICKFRAME) mwm_hints.decorations |= MWM_DECOR_BORDER | MWM_DECOR_RESIZEH;
438     else if ((win->dwStyle & (WS_DLGFRAME|WS_BORDER)) == WS_DLGFRAME) mwm_hints.decorations |= MWM_DECOR_BORDER;
439     else if (win->dwStyle & WS_BORDER) mwm_hints.decorations |= MWM_DECOR_BORDER;
440     else if (!(win->dwStyle & (WS_CHILD|WS_POPUP))) mwm_hints.decorations |= MWM_DECOR_BORDER;
441     if (win->dwStyle & WS_SYSMENU)  mwm_hints.decorations |= MWM_DECOR_MENU;
442     if (win->dwStyle & WS_MINIMIZEBOX) mwm_hints.decorations |= MWM_DECOR_MINIMIZE;
443     if (win->dwStyle & WS_MAXIMIZEBOX) mwm_hints.decorations |= MWM_DECOR_MAXIMIZE;
444
445     XChangeProperty( display, data->whole_window, x11drv_atom(_MOTIF_WM_HINTS),
446                      x11drv_atom(_MOTIF_WM_HINTS), 32, PropModeReplace,
447                      (char*)&mwm_hints, sizeof(mwm_hints)/sizeof(long) );
448
449     XChangeProperty( display, data->whole_window, x11drv_atom(XdndAware),
450                      XA_ATOM, 32, PropModeReplace, (unsigned char*)&dndVersion, 1 );
451
452     wm_hints = XAllocWMHints();
453     wine_tsx11_unlock();
454
455     /* wm hints */
456     if (wm_hints)
457     {
458         wm_hints->flags = InputHint | StateHint | WindowGroupHint;
459         wm_hints->input = !(win->dwStyle & WS_DISABLED);
460
461         set_icon_hints( display, win, wm_hints );
462
463         wm_hints->initial_state = (win->dwStyle & WS_MINIMIZE) ? IconicState : NormalState;
464         wm_hints->window_group = group_leader;
465
466         wine_tsx11_lock();
467         XSetWMHints( display, data->whole_window, wm_hints );
468         XFree(wm_hints);
469         wine_tsx11_unlock();
470     }
471 }
472
473
474 /***********************************************************************
475  *              X11DRV_set_iconic_state
476  *
477  * Set the X11 iconic state according to the window style.
478  */
479 void X11DRV_set_iconic_state( WND *win )
480 {
481     Display *display = thread_display();
482     struct x11drv_win_data *data = win->pDriverData;
483     XWMHints* wm_hints;
484     BOOL iconic = IsIconic( win->hwndSelf );
485
486     wine_tsx11_lock();
487
488     if (iconic) XUnmapWindow( display, data->client_window );
489     else if (is_client_window_mapped( win )) XMapWindow( display, data->client_window );
490
491     if (!(wm_hints = XGetWMHints( display, data->whole_window ))) wm_hints = XAllocWMHints();
492     wm_hints->flags |= StateHint | IconPositionHint;
493     wm_hints->initial_state = iconic ? IconicState : NormalState;
494     wm_hints->icon_x = win->rectWindow.left;
495     wm_hints->icon_y = win->rectWindow.top;
496     XSetWMHints( display, data->whole_window, wm_hints );
497
498     if (win->dwStyle & WS_VISIBLE)
499     {
500         if (iconic)
501             XIconifyWindow( display, data->whole_window, DefaultScreen(display) );
502         else
503             if (!IsRectEmpty( &win->rectWindow )) XMapWindow( display, data->whole_window );
504     }
505
506     XFree(wm_hints);
507     wine_tsx11_unlock();
508 }
509
510
511 /***********************************************************************
512  *              X11DRV_window_to_X_rect
513  *
514  * Convert a rect from client to X window coordinates
515  */
516 void X11DRV_window_to_X_rect( WND *win, RECT *rect )
517 {
518     RECT rc;
519
520     if (!(win->dwExStyle & WS_EX_MANAGED)) return;
521     if (IsRectEmpty( rect )) return;
522
523     rc.top = rc.bottom = rc.left = rc.right = 0;
524
525     AdjustWindowRectEx( &rc, win->dwStyle & ~(WS_HSCROLL|WS_VSCROLL), FALSE, win->dwExStyle );
526
527     rect->left   -= rc.left;
528     rect->right  -= rc.right;
529     rect->top    -= rc.top;
530     rect->bottom -= rc.bottom;
531     if (rect->top >= rect->bottom) rect->bottom = rect->top + 1;
532     if (rect->left >= rect->right) rect->right = rect->left + 1;
533 }
534
535
536 /***********************************************************************
537  *              X11DRV_X_to_window_rect
538  *
539  * Opposite of X11DRV_window_to_X_rect
540  */
541 void X11DRV_X_to_window_rect( WND *win, RECT *rect )
542 {
543     if (!(win->dwExStyle & WS_EX_MANAGED)) return;
544     if (IsRectEmpty( rect )) return;
545
546     AdjustWindowRectEx( rect, win->dwStyle & ~(WS_HSCROLL|WS_VSCROLL), FALSE, win->dwExStyle );
547
548     if (rect->top >= rect->bottom) rect->bottom = rect->top + 1;
549     if (rect->left >= rect->right) rect->right = rect->left + 1;
550 }
551
552
553 /***********************************************************************
554  *              X11DRV_sync_whole_window_position
555  *
556  * Synchronize the X whole window position with the Windows one
557  */
558 int X11DRV_sync_whole_window_position( Display *display, WND *win, int zorder )
559 {
560     XWindowChanges changes;
561     int mask;
562     struct x11drv_win_data *data = win->pDriverData;
563     RECT whole_rect = win->rectWindow;
564
565     X11DRV_window_to_X_rect( win, &whole_rect );
566     mask = get_window_changes( &changes, &data->whole_rect, &whole_rect );
567
568     if (zorder)
569     {
570         if (is_window_top_level( win ))
571         {
572             /* find window that this one must be after */
573             HWND prev = GetWindow( win->hwndSelf, GW_HWNDPREV );
574             while (prev && !(GetWindowLongW( prev, GWL_STYLE ) & WS_VISIBLE))
575                 prev = GetWindow( prev, GW_HWNDPREV );
576             if (!prev)  /* top child */
577             {
578                 changes.stack_mode = Above;
579                 mask |= CWStackMode;
580             }
581             else
582             {
583                 /* should use stack_mode Below but most window managers don't get it right */
584                 /* so move it above the next one in Z order */
585                 HWND next = GetWindow( win->hwndSelf, GW_HWNDNEXT );
586                 while (next && !(GetWindowLongW( next, GWL_STYLE ) & WS_VISIBLE))
587                     next = GetWindow( next, GW_HWNDNEXT );
588                 if (next)
589                 {
590                     changes.stack_mode = Above;
591                     changes.sibling = X11DRV_get_whole_window(next);
592                     mask |= CWStackMode | CWSibling;
593                 }
594             }
595         }
596         else
597         {
598             HWND next = GetWindow( win->hwndSelf, GW_HWNDNEXT );
599
600             if (win->parent == GetDesktopWindow() &&
601                 root_window != DefaultRootWindow(display))
602             {
603                 /* in desktop mode we need the sibling to belong to the same process */
604                 while (next)
605                 {
606                     WND *ptr = WIN_GetPtr( next );
607                     if (ptr != WND_OTHER_PROCESS)
608                     {
609                         WIN_ReleasePtr( ptr );
610                         break;
611                     }
612                     next = GetWindow( next, GW_HWNDNEXT );
613                 }
614             }
615
616             if (!next)  /* bottom child */
617             {
618                 changes.stack_mode = Below;
619                 mask |= CWStackMode;
620             }
621             else
622             {
623                 changes.stack_mode = Above;
624                 changes.sibling = X11DRV_get_whole_window(next);
625                 mask |= CWStackMode | CWSibling;
626             }
627         }
628     }
629
630     data->whole_rect = whole_rect;
631
632     if (mask)
633     {
634         TRACE( "setting win %lx pos %ld,%ld,%ldx%ld after %lx changes=%x\n",
635                data->whole_window, whole_rect.left, whole_rect.top,
636                whole_rect.right - whole_rect.left, whole_rect.bottom - whole_rect.top,
637                changes.sibling, mask );
638         wine_tsx11_lock();
639         XSync( gdi_display, False );  /* flush graphics operations before moving the window */
640         if (is_window_top_level( win ))
641         {
642             if (mask & (CWWidth|CWHeight)) set_size_hints( display, win );
643             XReconfigureWMWindow( display, data->whole_window,
644                                   DefaultScreen(display), mask, &changes );
645         }
646         else XConfigureWindow( display, data->whole_window, mask, &changes );
647         wine_tsx11_unlock();
648     }
649     return mask;
650 }
651
652
653 /***********************************************************************
654  *              X11DRV_sync_client_window_position
655  *
656  * Synchronize the X client window position with the Windows one
657  */
658 int X11DRV_sync_client_window_position( Display *display, WND *win )
659 {
660     XWindowChanges changes;
661     int mask;
662     struct x11drv_win_data *data = win->pDriverData;
663     RECT client_rect = win->rectClient;
664
665     OffsetRect( &client_rect, -data->whole_rect.left, -data->whole_rect.top );
666
667     if ((mask = get_window_changes( &changes, &data->client_rect, &client_rect )))
668     {
669         BOOL was_mapped = is_client_window_mapped( win );
670
671         TRACE( "setting win %lx pos %ld,%ld,%ldx%ld (was %ld,%ld,%ldx%ld) after %lx changes=%x\n",
672                data->client_window, client_rect.left, client_rect.top,
673                client_rect.right - client_rect.left, client_rect.bottom - client_rect.top,
674                data->client_rect.left, data->client_rect.top,
675                data->client_rect.right - data->client_rect.left,
676                data->client_rect.bottom - data->client_rect.top,
677                changes.sibling, mask );
678         data->client_rect = client_rect;
679         wine_tsx11_lock();
680         XSync( gdi_display, False );  /* flush graphics operations before moving the window */
681         if (was_mapped && !is_client_window_mapped( win ))
682             XUnmapWindow( display, data->client_window );
683         XConfigureWindow( display, data->client_window, mask, &changes );
684         if (!was_mapped && is_client_window_mapped( win ))
685             XMapWindow( display, data->client_window );
686         wine_tsx11_unlock();
687     }
688     return mask;
689 }
690
691
692 /***********************************************************************
693  *              X11DRV_register_window
694  *
695  * Associate an X window to a HWND.
696  */
697 void X11DRV_register_window( Display *display, HWND hwnd, struct x11drv_win_data *data )
698 {
699     wine_tsx11_lock();
700     XSaveContext( display, data->whole_window, winContext, (char *)hwnd );
701     XSaveContext( display, data->client_window, winContext, (char *)hwnd );
702     wine_tsx11_unlock();
703 }
704
705
706 /**********************************************************************
707  *              create_desktop
708  */
709 static void create_desktop( Display *display, WND *wndPtr )
710 {
711     X11DRV_WND_DATA *data = wndPtr->pDriverData;
712
713     wine_tsx11_lock();
714     winContext = XUniqueContext();
715     XInternAtoms( display, (char **)atom_names, NB_XATOMS - FIRST_XATOM, False, X11DRV_Atoms );
716     wine_tsx11_unlock();
717
718     whole_window_atom  = MAKEINTATOMA( GlobalAddAtomA( "__wine_x11_whole_window" ));
719     client_window_atom = MAKEINTATOMA( GlobalAddAtomA( "__wine_x11_client_window" ));
720     icon_window_atom   = MAKEINTATOMA( GlobalAddAtomA( "__wine_x11_icon_window" ));
721
722     data->whole_window = data->client_window = root_window;
723     data->whole_rect = data->client_rect = wndPtr->rectWindow;
724
725     SetPropA( wndPtr->hwndSelf, whole_window_atom, (HANDLE)root_window );
726     SetPropA( wndPtr->hwndSelf, client_window_atom, (HANDLE)root_window );
727     SetPropA( wndPtr->hwndSelf, "__wine_x11_visual_id", (HANDLE)XVisualIDFromVisual(visual) );
728
729     X11DRV_InitClipboard();
730
731     if (root_window != DefaultRootWindow(display)) X11DRV_create_desktop_thread();
732 }
733
734
735 /**********************************************************************
736  *              create_whole_window
737  *
738  * Create the whole X window for a given window
739  */
740 static Window create_whole_window( Display *display, WND *win )
741 {
742     struct x11drv_win_data *data = win->pDriverData;
743     int cx, cy, mask;
744     XSetWindowAttributes attr;
745     Window parent;
746     RECT rect;
747     BOOL is_top_level = is_window_top_level( win );
748
749     rect = win->rectWindow;
750     X11DRV_window_to_X_rect( win, &rect );
751
752     if (!(cx = rect.right - rect.left)) cx = 1;
753     if (!(cy = rect.bottom - rect.top)) cy = 1;
754
755     parent = X11DRV_get_client_window( win->parent );
756
757     wine_tsx11_lock();
758
759     mask = get_window_attributes( display, win, &attr );
760
761     /* set the attributes that don't change over the lifetime of the window */
762     attr.bit_gravity       = ForgetGravity;
763     attr.win_gravity       = NorthWestGravity;
764     attr.backing_store     = NotUseful/*WhenMapped*/;
765     mask |= CWBitGravity | CWWinGravity | CWBackingStore;
766
767     data->whole_rect = rect;
768     data->whole_window = XCreateWindow( display, parent, rect.left, rect.top, cx, cy,
769                                         0, screen_depth, InputOutput, visual,
770                                         mask, &attr );
771
772     if (!data->whole_window)
773     {
774         wine_tsx11_unlock();
775         return 0;
776     }
777
778     if (is_top_level)
779     {
780         XIM xim = x11drv_thread_data()->xim;
781         if (xim) data->xic = XCreateIC( xim,
782                                         XNInputStyle, XIMPreeditNothing | XIMStatusNothing,
783                                         XNClientWindow, data->whole_window,
784                                         XNFocusWindow, data->whole_window,
785                                         0 );
786     }
787
788     /* non-maximized child must be at bottom of Z order */
789     if ((win->dwStyle & (WS_CHILD|WS_MAXIMIZE)) == WS_CHILD)
790     {
791         XWindowChanges changes;
792         changes.stack_mode = Below;
793         XConfigureWindow( display, data->whole_window, CWStackMode, &changes );
794     }
795
796     wine_tsx11_unlock();
797
798     if (is_top_level) X11DRV_set_wm_hints( display, win );
799
800     return data->whole_window;
801 }
802
803
804 /**********************************************************************
805  *              create_client_window
806  *
807  * Create the client window for a given window
808  */
809 static Window create_client_window( Display *display, WND *win )
810 {
811     struct x11drv_win_data *data = win->pDriverData;
812     RECT rect = data->whole_rect;
813     XSetWindowAttributes attr;
814
815     OffsetRect( &rect, -data->whole_rect.left, -data->whole_rect.top );
816     data->client_rect = rect;
817
818     attr.event_mask = (ExposureMask | PointerMotionMask |
819                        ButtonPressMask | ButtonReleaseMask | EnterWindowMask);
820     attr.bit_gravity = (win->clsStyle & (CS_VREDRAW | CS_HREDRAW)) ?
821                        ForgetGravity : NorthWestGravity;
822     attr.backing_store = NotUseful/*WhenMapped*/;
823
824     wine_tsx11_lock();
825     data->client_window = XCreateWindow( display, data->whole_window, 0, 0,
826                                          max( rect.right - rect.left, 1 ),
827                                          max( rect.bottom - rect.top, 1 ),
828                                          0, screen_depth,
829                                          InputOutput, visual,
830                                          CWEventMask | CWBitGravity | CWBackingStore, &attr );
831     if (data->client_window && is_client_window_mapped( win ))
832         XMapWindow( display, data->client_window );
833     wine_tsx11_unlock();
834     return data->client_window;
835 }
836
837
838 /*****************************************************************
839  *              SetWindowText   (X11DRV.@)
840  */
841 BOOL X11DRV_SetWindowText( HWND hwnd, LPCWSTR text )
842 {
843     Display *display = thread_display();
844     UINT count;
845     char *buffer;
846     char *utf8_buffer;
847     Window win;
848     XTextProperty prop;
849
850     if ((win = X11DRV_get_whole_window( hwnd )))
851     {
852         /* allocate new buffer for window text */
853         count = WideCharToMultiByte(CP_UNIXCP, 0, text, -1, NULL, 0, NULL, NULL);
854         if (!(buffer = HeapAlloc( GetProcessHeap(), 0, count )))
855         {
856             ERR("Not enough memory for window text\n");
857             return FALSE;
858         }
859         WideCharToMultiByte(CP_UNIXCP, 0, text, -1, buffer, count, NULL, NULL);
860
861         count = WideCharToMultiByte(CP_UTF8, 0, text, strlenW(text), NULL, 0, NULL, NULL);
862         if (!(utf8_buffer = HeapAlloc( GetProcessHeap(), 0, count )))
863         {
864             ERR("Not enough memory for window text in UTF-8\n");
865             return FALSE;
866         }
867         WideCharToMultiByte(CP_UTF8, 0, text, strlenW(text), utf8_buffer, count, NULL, NULL);
868
869         wine_tsx11_lock();
870         if (XmbTextListToTextProperty( display, &buffer, 1, XStdICCTextStyle, &prop ) == Success)
871         {
872             XSetWMName( display, win, &prop );
873             XSetWMIconName( display, win, &prop );
874             XFree( prop.value );
875         }
876         /*
877         Implements a NET_WM UTF-8 title. It should be without a trailing \0,
878         according to the standard
879         ( http://www.pps.jussieu.fr/~jch/software/UTF8_STRING/UTF8_STRING.text ).
880         */
881         XChangeProperty( display, win, x11drv_atom(_NET_WM_NAME), x11drv_atom(UTF8_STRING),
882                          8, PropModeReplace, (unsigned char *) utf8_buffer, count);
883         wine_tsx11_unlock();
884
885         HeapFree( GetProcessHeap(), 0, utf8_buffer );
886         HeapFree( GetProcessHeap(), 0, buffer );
887     }
888     return TRUE;
889 }
890
891
892 /***********************************************************************
893  *              DestroyWindow   (X11DRV.@)
894  */
895 BOOL X11DRV_DestroyWindow( HWND hwnd )
896 {
897     struct x11drv_thread_data *thread_data = x11drv_thread_data();
898     Display *display = thread_data->display;
899     WND *wndPtr = WIN_GetPtr( hwnd );
900     X11DRV_WND_DATA *data = wndPtr->pDriverData;
901
902     if (!data) goto done;
903
904     if (data->whole_window)
905     {
906         TRACE( "win %p xwin %lx/%lx\n", hwnd, data->whole_window, data->client_window );
907         if (thread_data->cursor_window == data->whole_window) thread_data->cursor_window = None;
908         if (thread_data->last_focus == hwnd) thread_data->last_focus = 0;
909         wine_tsx11_lock();
910         XSync( gdi_display, False );  /* flush any reference to this drawable in GDI queue */
911         XDeleteContext( display, data->whole_window, winContext );
912         XDeleteContext( display, data->client_window, winContext );
913         XDestroyWindow( display, data->whole_window );  /* this destroys client too */
914         if (data->xic)
915         {
916             XUnsetICFocus( data->xic );
917             XDestroyIC( data->xic );
918         }
919         destroy_icon_window( display, wndPtr );
920         wine_tsx11_unlock();
921     }
922
923     if (data->hWMIconBitmap) DeleteObject( data->hWMIconBitmap );
924     if (data->hWMIconMask) DeleteObject( data->hWMIconMask);
925     HeapFree( GetProcessHeap(), 0, data );
926     wndPtr->pDriverData = NULL;
927  done:
928     WIN_ReleasePtr( wndPtr );
929     return TRUE;
930 }
931
932
933 /**********************************************************************
934  *              CreateWindow   (X11DRV.@)
935  */
936 BOOL X11DRV_CreateWindow( HWND hwnd, CREATESTRUCTA *cs, BOOL unicode )
937 {
938     Display *display = thread_display();
939     WND *wndPtr;
940     struct x11drv_win_data *data;
941     RECT rect;
942     CBT_CREATEWNDA cbtc;
943     BOOL ret = FALSE;
944
945     if (cs->cx > 65535)
946     {
947         ERR( "invalid window width %d\n", cs->cx );
948         cs->cx = 65535;
949     }
950     if (cs->cy > 65535)
951     {
952         ERR( "invalid window height %d\n", cs->cx );
953         cs->cy = 65535;
954     }
955
956     if (!(data = HeapAlloc(GetProcessHeap(), 0, sizeof(*data)))) return FALSE;
957     data->whole_window  = 0;
958     data->client_window = 0;
959     data->icon_window   = 0;
960     data->xic           = 0;
961     data->hWMIconBitmap = 0;
962     data->hWMIconMask   = 0;
963
964     wndPtr = WIN_GetPtr( hwnd );
965     wndPtr->pDriverData = data;
966
967     /* initialize the dimensions before sending WM_GETMINMAXINFO */
968     SetRect( &rect, cs->x, cs->y, cs->x + cs->cx, cs->y + cs->cy );
969     WIN_SetRectangles( hwnd, &rect, &rect );
970
971     if (!wndPtr->parent)
972     {
973         create_desktop( display, wndPtr );
974         WIN_ReleasePtr( wndPtr );
975         return TRUE;
976     }
977
978     if (!create_whole_window( display, wndPtr )) goto failed;
979     if (!create_client_window( display, wndPtr )) goto failed;
980     TSXSync( display, False );
981
982     SetPropA( hwnd, whole_window_atom, (HANDLE)data->whole_window );
983     SetPropA( hwnd, client_window_atom, (HANDLE)data->client_window );
984
985     /* Call the WH_CBT hook */
986     cbtc.lpcs = cs;
987     cbtc.hwndInsertAfter = HWND_TOP;
988     if (HOOK_CallHooks( WH_CBT, HCBT_CREATEWND, (WPARAM)hwnd, (LPARAM)&cbtc, unicode ))
989     {
990         TRACE("CBT-hook returned !0\n");
991         goto failed;
992     }
993
994     /* Send the WM_GETMINMAXINFO message and fix the size if needed */
995     if ((cs->style & WS_THICKFRAME) || !(cs->style & (WS_POPUP | WS_CHILD)))
996     {
997         POINT maxSize, maxPos, minTrack, maxTrack;
998
999         WIN_ReleasePtr( wndPtr );
1000         WINPOS_GetMinMaxInfo( hwnd, &maxSize, &maxPos, &minTrack, &maxTrack);
1001         if (maxSize.x < cs->cx) cs->cx = maxSize.x;
1002         if (maxSize.y < cs->cy) cs->cy = maxSize.y;
1003         if (cs->cx < minTrack.x ) cs->cx = minTrack.x;
1004         if (cs->cy < minTrack.y ) cs->cy = minTrack.y;
1005         if (cs->cx < 0) cs->cx = 0;
1006         if (cs->cy < 0) cs->cy = 0;
1007
1008         if (!(wndPtr = WIN_GetPtr( hwnd ))) return FALSE;
1009         SetRect( &rect, cs->x, cs->y, cs->x + cs->cx, cs->y + cs->cy );
1010         WIN_SetRectangles( hwnd, &rect, &rect );
1011         X11DRV_sync_whole_window_position( display, wndPtr, 0 );
1012     }
1013     WIN_ReleasePtr( wndPtr );
1014
1015     /* send WM_NCCREATE */
1016     TRACE( "hwnd %p cs %d,%d %dx%d\n", hwnd, cs->x, cs->y, cs->cx, cs->cy );
1017     if (unicode)
1018         ret = SendMessageW( hwnd, WM_NCCREATE, 0, (LPARAM)cs );
1019     else
1020         ret = SendMessageA( hwnd, WM_NCCREATE, 0, (LPARAM)cs );
1021     if (!ret)
1022     {
1023         WARN("aborted by WM_xxCREATE!\n");
1024         return FALSE;
1025     }
1026
1027     if (!(wndPtr = WIN_GetPtr(hwnd))) return FALSE;
1028
1029     X11DRV_sync_window_style( display, wndPtr );
1030
1031     /* send WM_NCCALCSIZE */
1032     rect = wndPtr->rectWindow;
1033     WIN_ReleasePtr( wndPtr );
1034     SendMessageW( hwnd, WM_NCCALCSIZE, FALSE, (LPARAM)&rect );
1035
1036     if (!(wndPtr = WIN_GetPtr(hwnd))) return FALSE;
1037     if (rect.left > rect.right || rect.top > rect.bottom) rect = wndPtr->rectWindow;
1038     WIN_SetRectangles( hwnd, &wndPtr->rectWindow, &rect );
1039     X11DRV_sync_client_window_position( display, wndPtr );
1040     X11DRV_register_window( display, hwnd, data );
1041
1042     TRACE( "win %p window %ld,%ld,%ld,%ld client %ld,%ld,%ld,%ld whole %ld,%ld,%ld,%ld X client %ld,%ld,%ld,%ld xwin %x/%x\n",
1043            hwnd, wndPtr->rectWindow.left, wndPtr->rectWindow.top,
1044            wndPtr->rectWindow.right, wndPtr->rectWindow.bottom,
1045            wndPtr->rectClient.left, wndPtr->rectClient.top,
1046            wndPtr->rectClient.right, wndPtr->rectClient.bottom,
1047            data->whole_rect.left, data->whole_rect.top,
1048            data->whole_rect.right, data->whole_rect.bottom,
1049            data->client_rect.left, data->client_rect.top,
1050            data->client_rect.right, data->client_rect.bottom,
1051            (unsigned int)data->whole_window, (unsigned int)data->client_window );
1052
1053     if ((wndPtr->dwStyle & (WS_CHILD|WS_MAXIMIZE)) == WS_CHILD)
1054         WIN_LinkWindow( hwnd, wndPtr->parent, HWND_BOTTOM );
1055     else
1056         WIN_LinkWindow( hwnd, wndPtr->parent, HWND_TOP );
1057
1058     WIN_ReleasePtr( wndPtr );
1059
1060     if (unicode)
1061         ret = (SendMessageW( hwnd, WM_CREATE, 0, (LPARAM)cs ) != -1);
1062     else
1063         ret = (SendMessageA( hwnd, WM_CREATE, 0, (LPARAM)cs ) != -1);
1064
1065     if (!ret)
1066     {
1067         WIN_UnlinkWindow( hwnd );
1068         return FALSE;
1069     }
1070
1071     /* Send the size messages */
1072
1073     if (!(wndPtr = WIN_FindWndPtr(hwnd))) return FALSE;
1074     if (!(wndPtr->flags & WIN_NEED_SIZE))
1075     {
1076         /* send it anyway */
1077         if (((wndPtr->rectClient.right-wndPtr->rectClient.left) <0)
1078             ||((wndPtr->rectClient.bottom-wndPtr->rectClient.top)<0))
1079             WARN("sending bogus WM_SIZE message 0x%08lx\n",
1080                  MAKELONG(wndPtr->rectClient.right-wndPtr->rectClient.left,
1081                           wndPtr->rectClient.bottom-wndPtr->rectClient.top));
1082         SendMessageW( hwnd, WM_SIZE, SIZE_RESTORED,
1083                       MAKELONG(wndPtr->rectClient.right-wndPtr->rectClient.left,
1084                                wndPtr->rectClient.bottom-wndPtr->rectClient.top));
1085         SendMessageW( hwnd, WM_MOVE, 0,
1086                       MAKELONG( wndPtr->rectClient.left, wndPtr->rectClient.top ) );
1087     }
1088
1089     /* Show the window, maximizing or minimizing if needed */
1090
1091     if (wndPtr->dwStyle & (WS_MINIMIZE | WS_MAXIMIZE))
1092     {
1093         extern UINT WINPOS_MinMaximize( HWND hwnd, UINT cmd, LPRECT rect ); /*FIXME*/
1094
1095         RECT newPos;
1096         UINT swFlag = (wndPtr->dwStyle & WS_MINIMIZE) ? SW_MINIMIZE : SW_MAXIMIZE;
1097         WIN_SetStyle( hwnd, wndPtr->dwStyle & ~(WS_MAXIMIZE | WS_MINIMIZE) );
1098         WINPOS_MinMaximize( hwnd, swFlag, &newPos );
1099         swFlag = ((wndPtr->dwStyle & WS_CHILD) || GetActiveWindow())
1100             ? SWP_NOACTIVATE | SWP_NOZORDER | SWP_FRAMECHANGED
1101             : SWP_NOZORDER | SWP_FRAMECHANGED;
1102         SetWindowPos( hwnd, 0, newPos.left, newPos.top,
1103                       newPos.right, newPos.bottom, swFlag );
1104     }
1105
1106     /* if the window was made visible set create struct flag so that
1107      * we do a proper ShowWindow later on */
1108     if (wndPtr->dwStyle & WS_VISIBLE) cs->style |= WS_VISIBLE;
1109
1110     WIN_ReleaseWndPtr( wndPtr );
1111     return TRUE;
1112
1113
1114  failed:
1115     X11DRV_DestroyWindow( hwnd );
1116     if (wndPtr) WIN_ReleasePtr( wndPtr );
1117     return FALSE;
1118 }
1119
1120
1121 /***********************************************************************
1122  *              X11DRV_get_client_window
1123  *
1124  * Return the X window associated with the client area of a window
1125  */
1126 Window X11DRV_get_client_window( HWND hwnd )
1127 {
1128     Window ret = 0;
1129     WND *win = WIN_GetPtr( hwnd );
1130
1131     if (win == WND_OTHER_PROCESS)
1132         return (Window)GetPropA( hwnd, client_window_atom );
1133
1134     if (win)
1135     {
1136         struct x11drv_win_data *data = win->pDriverData;
1137         ret = data->client_window;
1138         WIN_ReleasePtr( win );
1139     }
1140     return ret;
1141 }
1142
1143
1144 /***********************************************************************
1145  *              X11DRV_get_whole_window
1146  *
1147  * Return the X window associated with the full area of a window
1148  */
1149 Window X11DRV_get_whole_window( HWND hwnd )
1150 {
1151     Window ret = 0;
1152     WND *win = WIN_GetPtr( hwnd );
1153
1154     if (win == WND_OTHER_PROCESS)
1155         return (Window)GetPropA( hwnd, whole_window_atom );
1156
1157     if (win)
1158     {
1159         struct x11drv_win_data *data = win->pDriverData;
1160         ret = data->whole_window;
1161         WIN_ReleasePtr( win );
1162     }
1163     return ret;
1164 }
1165
1166
1167 /***********************************************************************
1168  *              X11DRV_get_ic
1169  *
1170  * Return the X input context associated with a window
1171  */
1172 XIC X11DRV_get_ic( HWND hwnd )
1173 {
1174     XIC ret = 0;
1175     WND *win = WIN_GetPtr( hwnd );
1176
1177     if (win && win != WND_OTHER_PROCESS)
1178     {
1179         struct x11drv_win_data *data = win->pDriverData;
1180         ret = data->xic;
1181         WIN_ReleasePtr( win );
1182     }
1183     return ret;
1184 }
1185
1186
1187 /*****************************************************************
1188  *              SetParent   (X11DRV.@)
1189  */
1190 HWND X11DRV_SetParent( HWND hwnd, HWND parent )
1191 {
1192     Display *display = thread_display();
1193     WND *wndPtr;
1194     HWND retvalue;
1195
1196     /* Windows hides the window first, then shows it again
1197      * including the WM_SHOWWINDOW messages and all */
1198     BOOL was_visible = ShowWindow( hwnd, SW_HIDE );
1199
1200     if (!IsWindow( parent )) return 0;
1201     if (!(wndPtr = WIN_GetPtr(hwnd)) || wndPtr == WND_OTHER_PROCESS) return 0;
1202
1203     retvalue = wndPtr->parent;  /* old parent */
1204     if (parent != retvalue)
1205     {
1206         struct x11drv_win_data *data = wndPtr->pDriverData;
1207
1208         WIN_LinkWindow( hwnd, parent, HWND_TOP );
1209
1210         if (parent != GetDesktopWindow()) /* a child window */
1211         {
1212             if (!(wndPtr->dwStyle & WS_CHILD))
1213             {
1214                 HMENU menu = (HMENU)SetWindowLongW( hwnd, GWL_ID, 0 );
1215                 if (menu) DestroyMenu( menu );
1216             }
1217         }
1218
1219         if (is_window_top_level( wndPtr )) X11DRV_set_wm_hints( display, wndPtr );
1220         wine_tsx11_lock();
1221         X11DRV_sync_window_style( display, wndPtr );
1222         XReparentWindow( display, data->whole_window, X11DRV_get_client_window(parent),
1223                          data->whole_rect.left, data->whole_rect.top );
1224         wine_tsx11_unlock();
1225     }
1226     WIN_ReleasePtr( wndPtr );
1227
1228     /* SetParent additionally needs to make hwnd the topmost window
1229        in the x-order and send the expected WM_WINDOWPOSCHANGING and
1230        WM_WINDOWPOSCHANGED notification messages.
1231     */
1232     SetWindowPos( hwnd, HWND_TOPMOST, 0, 0, 0, 0,
1233                   SWP_NOACTIVATE | SWP_NOMOVE | SWP_NOSIZE | (was_visible ? SWP_SHOWWINDOW : 0) );
1234     /* FIXME: a WM_MOVE is also generated (in the DefWindowProc handler
1235      * for WM_WINDOWPOSCHANGED) in Windows, should probably remove SWP_NOMOVE */
1236
1237     return retvalue;
1238 }
1239
1240
1241 /*****************************************************************
1242  *              SetFocus   (X11DRV.@)
1243  *
1244  * Set the X focus.
1245  * Explicit colormap management seems to work only with OLVWM.
1246  */
1247 void X11DRV_SetFocus( HWND hwnd )
1248 {
1249     Display *display = thread_display();
1250     XWindowAttributes win_attr;
1251     Window win;
1252
1253     /* Only mess with the X focus if there's */
1254     /* no desktop window and if the window is not managed by the WM. */
1255     if (root_window != DefaultRootWindow(display)) return;
1256
1257     if (!hwnd)  /* If setting the focus to 0, uninstall the colormap */
1258     {
1259         wine_tsx11_lock();
1260         if (X11DRV_PALETTE_PaletteFlags & X11DRV_PALETTE_PRIVATE)
1261             XUninstallColormap( display, X11DRV_PALETTE_PaletteXColormap );
1262         wine_tsx11_unlock();
1263         return;
1264     }
1265
1266     hwnd = GetAncestor( hwnd, GA_ROOT );
1267     if (GetWindowLongW( hwnd, GWL_EXSTYLE ) & WS_EX_MANAGED) return;
1268     if (!(win = X11DRV_get_whole_window( hwnd ))) return;
1269
1270     /* Set X focus and install colormap */
1271     wine_tsx11_lock();
1272     if (XGetWindowAttributes( display, win, &win_attr ) &&
1273         (win_attr.map_state == IsViewable))
1274     {
1275         /* If window is not viewable, don't change anything */
1276
1277         /* we must not use CurrentTime (ICCCM), so try to use last message time instead */
1278         /* FIXME: this is not entirely correct */
1279         XSetInputFocus( display, win, RevertToParent,
1280                         /*CurrentTime*/ GetMessageTime() + X11DRV_server_startticks );
1281         if (X11DRV_PALETTE_PaletteFlags & X11DRV_PALETTE_PRIVATE)
1282             XInstallColormap( display, X11DRV_PALETTE_PaletteXColormap );
1283     }
1284     wine_tsx11_unlock();
1285 }
1286
1287
1288 /**********************************************************************
1289  *              SetWindowIcon (X11DRV.@)
1290  *
1291  * hIcon or hIconSm has changed (or is being initialised for the
1292  * first time). Complete the X11 driver-specific initialisation
1293  * and set the window hints.
1294  *
1295  * This is not entirely correct, may need to create
1296  * an icon window and set the pixmap as a background
1297  */
1298 HICON X11DRV_SetWindowIcon( HWND hwnd, HICON icon, BOOL small )
1299 {
1300     WND *wndPtr;
1301     Display *display = thread_display();
1302     HICON old = (HICON)SetClassLongW(hwnd, small ? GCL_HICONSM : GCL_HICON, (LONG)icon );
1303
1304     SetWindowPos( hwnd, 0, 0, 0, 0, 0, SWP_FRAMECHANGED | SWP_NOSIZE |
1305                   SWP_NOMOVE | SWP_NOACTIVATE | SWP_NOZORDER );
1306
1307     if (!(wndPtr = WIN_GetPtr( hwnd )) || wndPtr == WND_OTHER_PROCESS) return old;
1308
1309     if (wndPtr->dwExStyle & WS_EX_MANAGED)
1310     {
1311         Window win = get_whole_window(wndPtr);
1312         XWMHints* wm_hints;
1313
1314         wine_tsx11_lock();
1315         if (!(wm_hints = XGetWMHints( display, win ))) wm_hints = XAllocWMHints();
1316         wine_tsx11_unlock();
1317         if (wm_hints)
1318         {
1319             set_icon_hints( display, wndPtr, wm_hints );
1320             wine_tsx11_lock();
1321             XSetWMHints( display, win, wm_hints );
1322             XFree( wm_hints );
1323             wine_tsx11_unlock();
1324         }
1325     }
1326     WIN_ReleasePtr( wndPtr );
1327     return old;
1328 }