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