Merged display.dll into USER.
[wine] / windows / x11drv / wnd.c
1 /*
2  * X11 windows driver
3  *
4  * Copyright 1993, 1994, 1995, 1996 Alexandre Julliard
5  *                             1993 David Metcalfe
6  *                       1995, 1996 Alex Korobka
7  */
8
9 #include "config.h"
10
11 #include <X11/Xatom.h>
12
13 #include "ts_xlib.h"
14 #include "ts_xutil.h"
15
16 #include <stdlib.h>
17 #include <string.h>
18
19 #include "bitmap.h"
20 #include "color.h"
21 #include "debugtools.h"
22 #include "dce.h"
23 #include "options.h"
24 #include "message.h"
25 #include "heap.h"
26 #include "win.h"
27 #include "windef.h"
28 #include "class.h"
29 #include "x11drv.h"
30 #include "wingdi.h"
31 #include "wine/winuser16.h"
32
33 DEFAULT_DEBUG_CHANNEL(win);
34
35   /* Some useful macros */
36 #define HAS_DLGFRAME(style,exStyle) \
37 ((!((style) & WS_THICKFRAME)) && (((style) & WS_DLGFRAME) || ((exStyle) & WS_EX_DLGMODALFRAME)))
38
39 /**********************************************************************/
40
41 extern Cursor X11DRV_MOUSE_XCursor;  /* Current X cursor */
42 extern BOOL   X11DRV_CreateBitmap( HBITMAP );
43 extern Pixmap X11DRV_BITMAP_Pixmap( HBITMAP );
44
45 /**********************************************************************/
46
47 /* X context to associate a hwnd to an X window */
48 XContext winContext = 0;
49
50 Atom wmProtocols = None;
51 Atom wmDeleteWindow = None;
52 Atom dndProtocol = None;
53 Atom dndSelection = None;
54 Atom wmChangeState = None;
55
56 Atom kwmDockWindow = None;
57
58 /***********************************************************************
59  *              X11DRV_WND_GetXWindow
60  *
61  * Return the X window associated to a window.
62  */
63 Window X11DRV_WND_GetXWindow(WND *wndPtr)
64 {
65     return wndPtr && wndPtr->pDriverData ? 
66       ((X11DRV_WND_DATA *) wndPtr->pDriverData)->window : 0;
67 }
68
69 /***********************************************************************
70  *              X11DRV_WND_FindXWindow
71  *
72  * Return the the first X window associated to a window chain.
73  */
74 Window X11DRV_WND_FindXWindow(WND *wndPtr)
75 {
76     while (wndPtr && 
77            !((X11DRV_WND_DATA *) wndPtr->pDriverData)->window) 
78       wndPtr = wndPtr->parent;
79     return wndPtr ?
80       ((X11DRV_WND_DATA *) wndPtr->pDriverData)->window : 0;
81 }
82
83 /***********************************************************************
84  *              X11DRV_WND_RegisterWindow
85  *
86  * Associate an X window to a HWND.
87  */
88 static void X11DRV_WND_RegisterWindow(WND *wndPtr)
89 {
90   TSXSetWMProtocols( display, X11DRV_WND_GetXWindow(wndPtr), &wmDeleteWindow, 1 );
91   
92   if (!winContext) winContext = TSXUniqueContext();
93   TSXSaveContext( display, X11DRV_WND_GetXWindow(wndPtr), 
94                   winContext, (char *) wndPtr->hwndSelf );
95 }
96
97 /**********************************************************************
98  *              X11DRV_WND_Initialize
99  */
100 void X11DRV_WND_Initialize(WND *wndPtr)
101 {
102   X11DRV_WND_DATA *pWndDriverData = 
103     (X11DRV_WND_DATA *) HeapAlloc(SystemHeap, 0, sizeof(X11DRV_WND_DATA));
104
105   wndPtr->pDriverData = (void *) pWndDriverData;
106
107   pWndDriverData->window = 0;
108 }
109
110 /**********************************************************************
111  *              X11DRV_WND_Finalize
112  */
113 void X11DRV_WND_Finalize(WND *wndPtr)
114 {
115   X11DRV_WND_DATA *pWndDriverData =
116     (X11DRV_WND_DATA *) wndPtr->pDriverData;
117
118   if (!wndPtr->pDriverData) {
119      ERR("Trying to destroy window again. Not good.\n");
120      return;
121   }
122   if(pWndDriverData->window)
123     {
124       ERR(
125           "WND destroyed without destroying "
126           "the associated X Window (%ld)\n", 
127           pWndDriverData->window
128       );
129     }
130   HeapFree(SystemHeap, 0, wndPtr->pDriverData);
131   wndPtr->pDriverData = NULL;
132 }
133
134 /**********************************************************************
135  *              X11DRV_WND_CreateDesktopWindow
136  */
137 BOOL X11DRV_WND_CreateDesktopWindow(WND *wndPtr, CLASS *classPtr, BOOL bUnicode)
138 {
139     if (wmProtocols == None)
140         wmProtocols = TSXInternAtom( display, "WM_PROTOCOLS", True );
141     if (wmDeleteWindow == None)
142         wmDeleteWindow = TSXInternAtom( display, "WM_DELETE_WINDOW", True );
143     if( dndProtocol == None )
144         dndProtocol = TSXInternAtom( display, "DndProtocol" , False );
145     if( dndSelection == None )
146         dndSelection = TSXInternAtom( display, "DndSelection" , False );
147     if( wmChangeState == None )
148         wmChangeState = TSXInternAtom (display, "WM_CHANGE_STATE", False);
149     if (kwmDockWindow == None)
150         kwmDockWindow = TSXInternAtom( display, "KWM_DOCKWINDOW", False );
151
152     ((X11DRV_WND_DATA *) wndPtr->pDriverData)->window = X11DRV_GetXRootWindow();
153     X11DRV_WND_RegisterWindow( wndPtr );
154
155     return TRUE;
156 }
157
158 /**********************************************************************
159  *              X11DRV_WND_IconChanged
160  *
161  * hIcon or hIconSm has changed (or is being initialised for the
162  * first time). Complete the X11 driver-specific initialisation.
163  *
164  * This is not entirely correct, may need to create
165  * an icon window and set the pixmap as a background
166  */
167 static void X11DRV_WND_IconChanged(WND *wndPtr)
168 {
169
170     HICON16 hIcon = NC_IconForWindow(wndPtr); 
171
172     if( ((X11DRV_WND_DATA *) wndPtr->pDriverData)->hWMIconBitmap )
173         DeleteObject( ((X11DRV_WND_DATA *) wndPtr->pDriverData)->hWMIconBitmap );
174
175     if( ((X11DRV_WND_DATA *) wndPtr->pDriverData)->hWMIconMask )
176         DeleteObject( ((X11DRV_WND_DATA *) wndPtr->pDriverData)->hWMIconMask);
177
178     if (!hIcon)
179     {
180         ((X11DRV_WND_DATA *) wndPtr->pDriverData)->hWMIconBitmap= 0;
181         ((X11DRV_WND_DATA *) wndPtr->pDriverData)->hWMIconMask= 0;
182     }
183     else
184     {
185         HBITMAP hbmOrig;
186         RECT rcMask;
187         BITMAP bmMask;
188         ICONINFO ii;
189         HDC hDC;
190
191         GetIconInfo(hIcon, &ii);
192
193         X11DRV_CreateBitmap(ii.hbmMask);
194         X11DRV_CreateBitmap(ii.hbmColor);
195
196         GetObjectA(ii.hbmMask, sizeof(bmMask), &bmMask);
197         rcMask.top    = 0;
198         rcMask.left   = 0;
199         rcMask.right  = bmMask.bmWidth;
200         rcMask.bottom = bmMask.bmHeight;
201
202         hDC = CreateCompatibleDC(0);
203         hbmOrig = SelectObject(hDC, ii.hbmMask);
204         InvertRect(hDC, &rcMask);
205         SelectObject(hDC, hbmOrig);
206         DeleteDC(hDC);
207
208         ((X11DRV_WND_DATA *) wndPtr->pDriverData)->hWMIconBitmap = ii.hbmColor;
209         ((X11DRV_WND_DATA *) wndPtr->pDriverData)->hWMIconMask= ii.hbmMask;
210     }
211     return;
212 }
213
214 static void X11DRV_WND_SetIconHints(WND *wndPtr, XWMHints *hints)
215 {
216     if (((X11DRV_WND_DATA *) wndPtr->pDriverData)->hWMIconBitmap)
217     {
218         hints->icon_pixmap
219             = X11DRV_BITMAP_Pixmap(((X11DRV_WND_DATA *) wndPtr->pDriverData)->hWMIconBitmap);
220         hints->flags |= IconPixmapHint;
221     }
222     else
223         hints->flags &= ~IconPixmapHint;
224
225     if (((X11DRV_WND_DATA *) wndPtr->pDriverData)->hWMIconMask)
226     {
227         hints->icon_mask
228             = X11DRV_BITMAP_Pixmap(((X11DRV_WND_DATA *) wndPtr->pDriverData)->hWMIconMask);
229         hints->flags |= IconMaskHint;
230     }
231     else
232         hints->flags &= ~IconMaskHint;
233 }
234
235 /**********************************************************************
236  *              X11DRV_WND_UpdateIconHints
237  *
238  * hIcon or hIconSm has changed (or is being initialised for the
239  * first time). Complete the X11 driver-specific initialisation
240  * and set the window hints.
241  *
242  * This is not entirely correct, may need to create
243  * an icon window and set the pixmap as a background
244  */
245 static void X11DRV_WND_UpdateIconHints(WND *wndPtr)
246 {
247     XWMHints* wm_hints;
248
249     X11DRV_WND_IconChanged(wndPtr);
250
251     wm_hints = TSXGetWMHints( display, X11DRV_WND_GetXWindow(wndPtr) );
252     if (!wm_hints) wm_hints = TSXAllocWMHints();
253     if (wm_hints)
254     {
255         X11DRV_WND_SetIconHints(wndPtr, wm_hints);
256         TSXSetWMHints( display, X11DRV_WND_GetXWindow(wndPtr), wm_hints );
257         TSXFree( wm_hints );
258     }
259 }
260
261
262 /**********************************************************************
263  *              X11DRV_WND_CreateWindow
264  */
265 BOOL X11DRV_WND_CreateWindow(WND *wndPtr, CLASS *classPtr, CREATESTRUCTA *cs, BOOL bUnicode)
266 {
267   /* Create the X window (only for top-level windows, and then only */
268   /* when there's no desktop window) */
269   
270   if (!(cs->style & WS_CHILD) && (X11DRV_GetXRootWindow() == DefaultRootWindow(display)))
271   {
272       Window    wGroupLeader;
273       XWMHints* wm_hints;
274       XSetWindowAttributes win_attr;
275       
276       /* Create "managed" windows only if a title bar or resizable */
277       /* frame is required. */
278         if (WIN_WindowNeedsWMBorder(cs->style, cs->dwExStyle)) {
279           win_attr.event_mask = ExposureMask | KeyPressMask |
280             KeyReleaseMask | PointerMotionMask |
281             ButtonPressMask | ButtonReleaseMask |
282             FocusChangeMask | StructureNotifyMask;
283           win_attr.override_redirect = FALSE;
284           wndPtr->flags |= WIN_MANAGED;
285         } else {
286           win_attr.event_mask = ExposureMask | KeyPressMask |
287             KeyReleaseMask | PointerMotionMask |
288             ButtonPressMask | ButtonReleaseMask |
289             FocusChangeMask;
290           win_attr.override_redirect = TRUE;
291         }
292       wndPtr->flags |= WIN_NATIVE;
293
294       win_attr.bit_gravity   = (classPtr->style & (CS_VREDRAW | CS_HREDRAW)) ? BGForget : BGNorthWest;
295       win_attr.colormap      = X11DRV_PALETTE_PaletteXColormap;
296       win_attr.backing_store = NotUseful;
297       win_attr.save_under    = ((classPtr->style & CS_SAVEBITS) != 0);
298       win_attr.cursor        = X11DRV_MOUSE_XCursor;
299
300       ((X11DRV_WND_DATA *) wndPtr->pDriverData)->hWMIconBitmap = 0;
301       ((X11DRV_WND_DATA *) wndPtr->pDriverData)->hWMIconMask = 0;
302       ((X11DRV_WND_DATA *) wndPtr->pDriverData)->bit_gravity = win_attr.bit_gravity;
303       ((X11DRV_WND_DATA *) wndPtr->pDriverData)->window = 
304         TSXCreateWindow( display, X11DRV_GetXRootWindow(), 
305                          cs->x, cs->y, cs->cx, cs->cy, 
306                          0, CopyFromParent, 
307                          InputOutput, CopyFromParent,
308                          CWEventMask | CWOverrideRedirect |
309                          CWColormap | CWCursor | CWSaveUnder |
310                          CWBackingStore | CWBitGravity, 
311                          &win_attr );
312       
313       if(!(wGroupLeader = X11DRV_WND_GetXWindow(wndPtr)))
314         return FALSE;
315
316       /* If we are the systray, we need to be managed to be noticed by KWM */
317
318       if (wndPtr->dwExStyle & WS_EX_TRAYWINDOW)
319         X11DRV_WND_DockWindow(wndPtr);
320
321       if (wndPtr->flags & WIN_MANAGED) 
322       {
323           XClassHint *class_hints = TSXAllocClassHint();
324           XSizeHints* size_hints = TSXAllocSizeHints();
325           
326           if (class_hints) 
327           {
328               class_hints->res_name = "wineManaged";
329               class_hints->res_class = "Wine";
330               TSXSetClassHint( display, ((X11DRV_WND_DATA *) wndPtr->pDriverData)->window, class_hints );
331               TSXFree (class_hints);
332           }
333
334           if (size_hints) 
335           {
336               size_hints->win_gravity = StaticGravity;
337               size_hints->flags = PWinGravity;
338
339               if (HAS_DLGFRAME(cs->style,cs->dwExStyle))
340               {
341                   size_hints->min_width = size_hints->max_width = cs->cx;
342                   size_hints->min_height = size_hints->max_height = cs->cy;
343                   size_hints->flags |= PMinSize | PMaxSize;
344               }
345
346               TSXSetWMSizeHints( display, X11DRV_WND_GetXWindow(wndPtr), 
347                                  size_hints, XA_WM_NORMAL_HINTS );
348               TSXFree(size_hints);
349           }
350       }
351       
352       if (cs->hwndParent)  /* Get window owner */
353       {
354           Window w;
355           WND *tmpWnd = WIN_FindWndPtr(cs->hwndParent);
356
357           w = X11DRV_WND_FindXWindow( tmpWnd );
358           if (w != None)
359           {
360               TSXSetTransientForHint( display, X11DRV_WND_GetXWindow(wndPtr), w );
361               wGroupLeader = w;
362           }
363           WIN_ReleaseWndPtr(tmpWnd);
364       }
365
366       if ((wm_hints = TSXAllocWMHints()))
367       {
368           wm_hints->flags = InputHint | StateHint | WindowGroupHint;
369           wm_hints->input = True;
370
371           if( wndPtr->flags & WIN_MANAGED )
372           {
373               X11DRV_WND_IconChanged(wndPtr);
374               X11DRV_WND_SetIconHints(wndPtr, wm_hints);
375
376               wm_hints->initial_state = (wndPtr->dwStyle & WS_MINIMIZE) 
377                                         ? IconicState : NormalState;
378           }
379           else
380               wm_hints->initial_state = NormalState;
381           wm_hints->window_group = wGroupLeader;
382
383           TSXSetWMHints( display, X11DRV_WND_GetXWindow(wndPtr), wm_hints );
384           TSXFree(wm_hints);
385       }
386       X11DRV_WND_RegisterWindow( wndPtr );
387   }
388   return TRUE;
389 }
390
391 /***********************************************************************
392  *              X11DRV_WND_DestroyWindow
393  */
394 BOOL X11DRV_WND_DestroyWindow(WND *wndPtr)
395 {
396    Window w;
397    if ((w = X11DRV_WND_GetXWindow(wndPtr)))
398    {
399        XEvent xe;
400        TSXDeleteContext( display, w, winContext );
401        TSXDestroyWindow( display, w );
402        while( TSXCheckWindowEvent(display, w, NoEventMask, &xe) );
403
404        ((X11DRV_WND_DATA *) wndPtr->pDriverData)->window = None;
405        if( ((X11DRV_WND_DATA *) wndPtr->pDriverData)->hWMIconBitmap )
406        {
407            DeleteObject( ((X11DRV_WND_DATA *) wndPtr->pDriverData)->hWMIconBitmap );
408            ((X11DRV_WND_DATA *) wndPtr->pDriverData)->hWMIconBitmap = 0;
409        }
410        if( ((X11DRV_WND_DATA *) wndPtr->pDriverData)->hWMIconMask )
411        {
412            DeleteObject( ((X11DRV_WND_DATA *) wndPtr->pDriverData)->hWMIconMask);
413            ((X11DRV_WND_DATA *) wndPtr->pDriverData)->hWMIconMask= 0;
414        }
415    }
416
417    return TRUE;
418 }
419
420 /*****************************************************************
421  *              X11DRV_WND_SetParent
422  */
423 WND *X11DRV_WND_SetParent(WND *wndPtr, WND *pWndParent)
424 {
425     WND *pDesktop = WIN_GetDesktop();
426     
427     if( wndPtr && pWndParent && (wndPtr != pDesktop) )
428     {
429         WND* pWndPrev = wndPtr->parent;
430
431         if( pWndParent != pWndPrev )
432         {
433             if ( X11DRV_WND_GetXWindow(wndPtr) )
434             {
435                 /* Toplevel window needs to be reparented.  Used by Tk 8.0 */
436
437                 TSXDestroyWindow( display, X11DRV_WND_GetXWindow(wndPtr) );
438                 ((X11DRV_WND_DATA *) wndPtr->pDriverData)->window = None;
439             }
440
441             WIN_UnlinkWindow(wndPtr->hwndSelf);
442             wndPtr->parent = pWndParent;
443
444             /* Create an X counterpart for reparented top-level windows
445              * when not in the desktop mode. */
446
447             if( pWndParent == pDesktop )
448             {
449                 wndPtr->dwStyle &= ~WS_CHILD;
450                 wndPtr->wIDmenu = 0;
451                 if( X11DRV_GetXRootWindow() == DefaultRootWindow(display) )
452                 {
453                     CREATESTRUCTA cs;
454                     cs.lpCreateParams = NULL;
455                     cs.hInstance = 0; /* not used in following call */
456                     cs.hMenu = 0; /* not used in following call */
457                     cs.hwndParent = pWndParent->hwndSelf;
458                     cs.cy = wndPtr->rectWindow.bottom - wndPtr->rectWindow.top;
459                     if (!cs.cy)
460                       cs.cy = 1;
461                     cs.cx = wndPtr->rectWindow.right - wndPtr->rectWindow.left;
462                     if (!cs.cx)
463                       cs.cx = 1;
464                     cs.y = wndPtr->rectWindow.top;
465                     cs.x = wndPtr->rectWindow.left;
466                     cs.style = wndPtr->dwStyle;
467                     cs.lpszName = 0; /* not used in following call */
468                     cs.lpszClass = 0; /*not used in following call */
469                     cs.dwExStyle = wndPtr->dwExStyle;
470                     X11DRV_WND_CreateWindow(wndPtr, wndPtr->class,
471                                             &cs, FALSE);
472                 }
473             }
474             else /* a child window */
475             {
476                 if( !( wndPtr->dwStyle & WS_CHILD ) )
477                 {
478                     wndPtr->dwStyle |= WS_CHILD;
479                     if( wndPtr->wIDmenu != 0)
480                     {
481                         DestroyMenu( (HMENU) wndPtr->wIDmenu );
482                         wndPtr->wIDmenu = 0;
483                     }
484                 }
485             }
486             WIN_LinkWindow(wndPtr->hwndSelf, HWND_TOP);
487         }
488         WIN_ReleaseDesktop();
489         return pWndPrev;
490     } /* failure */
491     WIN_ReleaseDesktop();
492     return 0;
493 }
494
495 /***********************************************************************
496  *              X11DRV_WND_ForceWindowRaise
497  *
498  * Raise a window on top of the X stacking order, while preserving 
499  * the correct Windows Z order.
500  */
501 void X11DRV_WND_ForceWindowRaise(WND *wndPtr)
502 {
503   XWindowChanges winChanges;
504   WND *wndPrev,*pDesktop = WIN_GetDesktop();
505   
506   if( !wndPtr || !X11DRV_WND_GetXWindow(wndPtr) || (wndPtr->flags & WIN_MANAGED) )
507   {
508       WIN_ReleaseDesktop();
509     return;
510   }
511   
512   /* Raise all windows up to wndPtr according to their Z order.
513    * (it would be easier with sibling-related Below but it doesn't
514    * work very well with SGI mwm for instance)
515    */
516   winChanges.stack_mode = Above;
517   while (wndPtr)
518     {
519       if (X11DRV_WND_GetXWindow(wndPtr)) 
520         TSXReconfigureWMWindow( display, X11DRV_WND_GetXWindow(wndPtr), 0,
521                                 CWStackMode, &winChanges );
522       wndPrev = pDesktop->child;
523       if (wndPrev == wndPtr) break;
524       while (wndPrev && (wndPrev->next != wndPtr)) wndPrev = wndPrev->next;
525       wndPtr = wndPrev;
526     }
527   WIN_ReleaseDesktop();
528 }
529
530 /***********************************************************************
531  *              X11DRV_WND_FindDesktopXWindow   [Internal]
532  *
533  * Find the actual X window which needs be restacked.
534  * Used by X11DRV_WND_SetWindowPos().
535  */
536 static Window X11DRV_WND_FindDesktopXWindow( WND *wndPtr )
537 {
538   if (!(wndPtr->flags & WIN_MANAGED))
539     return X11DRV_WND_GetXWindow(wndPtr);
540   else
541     {
542       Window window, root, parent, *children;
543       int nchildren;
544       window = X11DRV_WND_GetXWindow(wndPtr);
545       for (;;)
546         {
547           TSXQueryTree( display, window, &root, &parent,
548                         &children, &nchildren );
549           TSXFree( children );
550           if (parent == root)
551             return window;
552           window = parent;
553         }
554     }
555 }
556
557 /***********************************************************************
558  *           WINPOS_SetXWindowPos
559  *
560  * SetWindowPos() for an X window. Used by the real SetWindowPos().
561  */
562 void X11DRV_WND_SetWindowPos(WND *wndPtr, const WINDOWPOS *winpos, BOOL bChangePos)
563 {
564     XWindowChanges winChanges;
565     int changeMask = 0;
566     WND *winposPtr = WIN_FindWndPtr( winpos->hwnd );
567     if ( !winposPtr ) return;
568
569     if(!wndPtr->hwndSelf) wndPtr = NULL; /* FIXME: WND destroyed, shouldn't happen!!! */
570   
571     if (!(winpos->flags & SWP_SHOWWINDOW) && (winpos->flags & SWP_HIDEWINDOW))
572     {
573       if(X11DRV_WND_GetXWindow(wndPtr)) 
574         TSXUnmapWindow( display, X11DRV_WND_GetXWindow(wndPtr) );
575     }
576
577     if(bChangePos)
578     {
579         if ( !(winpos->flags & SWP_NOSIZE))
580         {
581           winChanges.width     = (winpos->cx > 0 ) ? winpos->cx : 1;
582           winChanges.height    = (winpos->cy > 0 ) ? winpos->cy : 1;
583           changeMask |= CWWidth | CWHeight;
584           
585           /* Tweak dialog window size hints */
586           
587           if ((winposPtr->flags & WIN_MANAGED) &&
588                HAS_DLGFRAME(winposPtr->dwStyle,winposPtr->dwExStyle))
589             {
590               XSizeHints *size_hints = TSXAllocSizeHints();
591               
592               if (size_hints)
593                 {
594                   long supplied_return;
595                   
596                   TSXGetWMSizeHints( display, X11DRV_WND_GetXWindow(winposPtr), size_hints,
597                                      &supplied_return, XA_WM_NORMAL_HINTS);
598                   size_hints->min_width = size_hints->max_width = winpos->cx;
599                   size_hints->min_height = size_hints->max_height = winpos->cy;
600                   TSXSetWMSizeHints( display, X11DRV_WND_GetXWindow(winposPtr), size_hints,
601                                      XA_WM_NORMAL_HINTS );
602                   TSXFree(size_hints);
603                 }
604             }
605         }
606         if (!(winpos->flags & SWP_NOMOVE))
607         {
608           winChanges.x = winpos->x;
609           winChanges.y = winpos->y;
610           changeMask |= CWX | CWY;
611         }
612         if (!(winpos->flags & SWP_NOZORDER))
613         {
614           winChanges.stack_mode = Below;
615           changeMask |= CWStackMode;
616           
617           if (winpos->hwndInsertAfter == HWND_TOP) winChanges.stack_mode = Above;
618           else if (winpos->hwndInsertAfter != HWND_BOTTOM)
619             {
620               WND*   insertPtr = WIN_FindWndPtr( winpos->hwndInsertAfter );
621               Window stack[2];
622               
623               stack[0] = X11DRV_WND_FindDesktopXWindow( insertPtr );
624               stack[1] = X11DRV_WND_FindDesktopXWindow( winposPtr );
625               
626               /* for stupid window managers (i.e. all of them) */
627               
628               TSXRestackWindows(display, stack, 2); 
629               changeMask &= ~CWStackMode;
630               
631               WIN_ReleaseWndPtr(insertPtr);
632             }
633         }
634         if (changeMask && X11DRV_WND_GetXWindow(winposPtr))
635         {
636             TSXReconfigureWMWindow( display, X11DRV_WND_GetXWindow(winposPtr), 0, changeMask, &winChanges );
637             if( winposPtr->class->style & (CS_VREDRAW | CS_HREDRAW) )
638                 X11DRV_WND_SetHostAttr( winposPtr, HAK_BITGRAVITY, BGForget );
639         }
640     }
641
642     if ( winpos->flags & SWP_SHOWWINDOW )
643     {
644         if(X11DRV_WND_GetXWindow(wndPtr)) 
645            TSXMapWindow( display, X11DRV_WND_GetXWindow(wndPtr) );
646     }
647     WIN_ReleaseWndPtr(winposPtr);
648 }
649
650 /*****************************************************************
651  *              X11DRV_WND_SetText
652  */
653 void X11DRV_WND_SetText(WND *wndPtr, LPCSTR text)
654 {   
655   if (!X11DRV_WND_GetXWindow(wndPtr))
656     return;
657
658   TSXStoreName( display, X11DRV_WND_GetXWindow(wndPtr), text );
659   TSXSetIconName( display, X11DRV_WND_GetXWindow(wndPtr), text );
660 }
661
662 /*****************************************************************
663  *              X11DRV_WND_SetFocus
664  *
665  * Set the X focus.
666  * Explicit colormap management seems to work only with OLVWM.
667  */
668 void X11DRV_WND_SetFocus(WND *wndPtr)
669 {
670   HWND hwnd =  wndPtr->hwndSelf;
671   XWindowAttributes win_attr;
672   Window win;
673   WND *w = wndPtr;
674   
675   /* Only mess with the X focus if there's */
676   /* no desktop window and if the window is not managed by the WM. */
677   if ((X11DRV_GetXRootWindow() != DefaultRootWindow(display))) return;
678   while (w && !((X11DRV_WND_DATA *) w->pDriverData)->window)
679       w = w->parent;
680   if (!w) w = wndPtr;
681   if (w->flags & WIN_MANAGED) return;
682
683   if (!hwnd)    /* If setting the focus to 0, uninstall the colormap */
684     {
685       if (X11DRV_PALETTE_PaletteFlags & X11DRV_PALETTE_PRIVATE)
686         TSXUninstallColormap( display, X11DRV_PALETTE_PaletteXColormap );
687       return;
688     }
689   
690   /* Set X focus and install colormap */
691   
692   if (!(win = X11DRV_WND_FindXWindow(wndPtr))) return;
693   if (!TSXGetWindowAttributes( display, win, &win_attr ) ||
694       (win_attr.map_state != IsViewable))
695     return;  /* If window is not viewable, don't change anything */
696   
697   TSXSetInputFocus( display, win, RevertToParent, CurrentTime );
698   if (X11DRV_PALETTE_PaletteFlags & X11DRV_PALETTE_PRIVATE)
699     TSXInstallColormap( display, X11DRV_PALETTE_PaletteXColormap );
700   
701   EVENT_Synchronize();
702 }
703
704 /*****************************************************************
705  *              X11DRV_WND_PreSizeMove
706  */
707 void X11DRV_WND_PreSizeMove(WND *wndPtr)
708 {
709   if (!(wndPtr->dwStyle & WS_CHILD) && (X11DRV_GetXRootWindow() == DefaultRootWindow(display)))
710     TSXGrabServer( display );
711 }
712
713 /*****************************************************************
714  *               X11DRV_WND_PostSizeMove
715  */
716 void X11DRV_WND_PostSizeMove(WND *wndPtr)
717 {
718   if (!(wndPtr->dwStyle & WS_CHILD) && 
719       (X11DRV_GetXRootWindow() == DefaultRootWindow(display)))
720     TSXUngrabServer( display );
721 }
722
723 /*****************************************************************
724  *               X11DRV_WND_SurfaceCopy
725  *
726  * Copies rect to (rect.left + dx, rect.top + dy). 
727  */
728 void X11DRV_WND_SurfaceCopy(WND* wndPtr, DC *dcPtr, INT dx, INT dy, 
729                             const RECT *rect, BOOL bUpdate)
730 {
731     X11DRV_PDEVICE *physDev = (X11DRV_PDEVICE *)dcPtr->physDev;
732     POINT dst, src;
733   
734     dst.x = (src.x = dcPtr->w.DCOrgX + rect->left) + dx;
735     dst.y = (src.y = dcPtr->w.DCOrgY + rect->top) + dy;
736   
737     if (bUpdate) /* handles non-Wine windows hanging over the copied area */
738         TSXSetGraphicsExposures( display, physDev->gc, True );
739     TSXSetFunction( display, physDev->gc, GXcopy );
740     TSXCopyArea( display, physDev->drawable, physDev->drawable,
741                  physDev->gc, src.x, src.y,
742                  rect->right - rect->left,
743                  rect->bottom - rect->top,
744                  dst.x, dst.y );
745     if (bUpdate)
746         TSXSetGraphicsExposures( display, physDev->gc, False );
747
748     if (bUpdate) /* Make sure exposure events have been processed */
749         EVENT_Synchronize();
750 }
751
752 /***********************************************************************
753  *              X11DRV_WND_SetDrawable
754  *
755  * Set the drawable, origin and dimensions for the DC associated to
756  * a given window.
757  */
758 void X11DRV_WND_SetDrawable(WND *wndPtr, DC *dc, WORD flags, BOOL bSetClipOrigin)
759 {
760     X11DRV_PDEVICE *physDev = (X11DRV_PDEVICE *)dc->physDev;
761     INT dcOrgXCopy = 0, dcOrgYCopy = 0;
762     BOOL offsetClipRgn = FALSE;
763
764     if (!wndPtr)  /* Get a DC for the whole screen */
765     {
766         dc->w.DCOrgX = 0;
767         dc->w.DCOrgY = 0;
768         physDev->drawable = X11DRV_GetXRootWindow();
769         TSXSetSubwindowMode( display, physDev->gc, IncludeInferiors );
770     }
771     else
772     {
773         /*
774          * This function change the coordinate system (DCOrgX,DCOrgY)
775          * values. When it moves the origin, other data like the current clipping
776          * region will not be moved to that new origin. In the case of DCs that are class
777          * or window DCs that clipping region might be a valid value from a previous use
778          * of the DC and changing the origin of the DC without moving the clip region
779          * results in a clip region that is not placed properly in the DC.
780          * This code will save the dc origin, let the SetDrawable
781          * modify the origin and reset the clipping. When the clipping is set,
782          * it is moved according to the new DC origin.
783          */
784          if ( (wndPtr->class->style & (CS_OWNDC | CS_CLASSDC)) && (dc->w.hClipRgn > 0))
785          {
786              dcOrgXCopy = dc->w.DCOrgX;
787              dcOrgYCopy = dc->w.DCOrgY;
788              offsetClipRgn = TRUE;
789          }
790
791         if (flags & DCX_WINDOW)
792         {
793             dc->w.DCOrgX  = wndPtr->rectWindow.left;
794             dc->w.DCOrgY  = wndPtr->rectWindow.top;
795         }
796         else
797         {
798             dc->w.DCOrgX  = wndPtr->rectClient.left;
799             dc->w.DCOrgY  = wndPtr->rectClient.top;
800         }
801         while (!X11DRV_WND_GetXWindow(wndPtr))
802         {
803             wndPtr = wndPtr->parent;
804             dc->w.DCOrgX += wndPtr->rectClient.left;
805             dc->w.DCOrgY += wndPtr->rectClient.top;
806         }
807         dc->w.DCOrgX -= wndPtr->rectWindow.left;
808         dc->w.DCOrgY -= wndPtr->rectWindow.top;
809
810         /* reset the clip region, according to the new origin */
811         if ( offsetClipRgn )
812         {
813              OffsetRgn(dc->w.hClipRgn, dc->w.DCOrgX - dcOrgXCopy,dc->w.DCOrgY - dcOrgYCopy);
814         }
815         
816         physDev->drawable = X11DRV_WND_GetXWindow(wndPtr);
817
818 #if 0
819         /* This is needed when we reuse a cached DC because
820          * SetDCState() called by ReleaseDC() screws up DC
821          * origins for child windows.
822          */
823
824         if( bSetClipOrigin )
825             TSXSetClipOrigin( display, physDev->gc, dc->w.DCOrgX, dc->w.DCOrgY );
826 #endif
827     }
828 }
829
830 /***********************************************************************
831  *              X11DRV_SetWMHint
832  */
833 static BOOL X11DRV_SetWMHint(Display* display, WND* wndPtr, int hint, int val)
834 {
835     XWMHints* wm_hints = TSXGetWMHints( display, X11DRV_WND_GetXWindow(wndPtr) );
836     if (!wm_hints) wm_hints = TSXAllocWMHints();
837     if (wm_hints)
838     {
839         wm_hints->flags = hint;
840         switch( hint )
841         {
842             case InputHint:
843                  wm_hints->input = val;
844                  break;
845
846             case StateHint:
847                  wm_hints->initial_state = val;
848                  break;
849
850             case IconPixmapHint:
851                  wm_hints->icon_pixmap = (Pixmap)val;
852                  break;
853
854             case IconWindowHint:
855                  wm_hints->icon_window = (Window)val;
856                  break;
857         }
858
859         TSXSetWMHints( display, X11DRV_WND_GetXWindow(wndPtr), wm_hints );
860         TSXFree(wm_hints);
861         return TRUE;
862     }
863     return FALSE;
864 }
865
866
867 /***********************************************************************
868  *              X11DRV_WND_SetHostAttr
869  *
870  * This function returns TRUE if the attribute is supported and the
871  * action was successful. Otherwise it should return FALSE and Wine will try 
872  * to get by without the functionality provided by the host window system.
873  */
874 BOOL X11DRV_WND_SetHostAttr(WND* wnd, INT ha, INT value)
875 {
876     Window w;
877
878     if( (w = X11DRV_WND_GetXWindow(wnd)) )
879     {
880         XSetWindowAttributes win_attr;
881
882         switch( ha )
883         {
884         case HAK_ICONICSTATE: /* called when a window is minimized/restored */
885
886                     if( (wnd->flags & WIN_MANAGED) )
887                     {
888                         if( value )
889                         {
890                             if( wnd->dwStyle & WS_VISIBLE )
891                             {
892                                 XClientMessageEvent ev;
893
894                                 /* FIXME: set proper icon */
895
896                                 ev.type = ClientMessage;
897                                 ev.display = display;
898                                 ev.message_type = wmChangeState;
899                                 ev.format = 32;
900                                 ev.data.l[0] = IconicState;
901                                 ev.window = w;
902
903                                 if( TSXSendEvent (display,
904                 RootWindow( display, XScreenNumberOfScreen(X11DRV_GetXScreen()) ), 
905                 True, (SubstructureRedirectMask | SubstructureNotifyMask), (XEvent*)&ev))
906                                 {
907                                     XEvent xe;
908                                     TSXFlush (display);
909                                     while( !TSXCheckTypedWindowEvent( display, w, UnmapNotify, &xe) );
910                                 }
911                                 else 
912                                     break;
913                             }
914                             else
915                                 X11DRV_SetWMHint( display, wnd, StateHint, IconicState );
916                         }
917                         else
918                         {
919                             if( !(wnd->flags & WS_VISIBLE) )
920                                 X11DRV_SetWMHint( display, wnd, StateHint, NormalState );
921                             else
922                             {
923                                 XEvent xe;
924                                 TSXMapWindow(display, w );
925                                 while( !TSXCheckTypedWindowEvent( display, w, MapNotify, &xe) );
926                             }
927                         }
928                         return TRUE;
929                     }
930                     break;
931
932         case HAK_BITGRAVITY: /* called when a window is resized */
933
934                     if( ((X11DRV_WND_DATA *) wnd->pDriverData)->bit_gravity != value )
935                     {
936                         win_attr.bit_gravity = value;
937                         ((X11DRV_WND_DATA *) wnd->pDriverData)->bit_gravity = value;
938                         TSXChangeWindowAttributes( display, w, CWBitGravity, &win_attr );
939                     }
940                    return TRUE;
941
942         case HAK_ICONS: /* called when the icons change */
943             if ( (wnd->flags & WIN_MANAGED) )
944                 X11DRV_WND_UpdateIconHints(wnd);
945             return TRUE;
946
947         case HAK_ACCEPTFOCUS: /* called when a window is disabled/enabled */
948
949                 if( (wnd->flags & WIN_MANAGED) )
950                     return X11DRV_SetWMHint( display, wnd, InputHint, value );
951         }
952     }
953     return FALSE;
954 }
955
956 /***********************************************************************
957  *              X11DRV_WND_IsSelfClipping
958  */
959 BOOL X11DRV_WND_IsSelfClipping(WND *wndPtr)
960 {
961   return X11DRV_WND_GetXWindow(wndPtr) != None;
962 }
963
964 /***********************************************************************
965  *              X11DRV_WND_DockWindow
966  *
967  * Set the X Property of the window that tells the windowmanager we really
968  * want to be in the systray
969  *
970  * KDE: set "KWM_DOCKWINDOW", type "KWM_DOCKWINDOW" to 1 before a window is 
971  *      mapped.
972  *
973  * all others: to be added ;)
974  */
975 void X11DRV_WND_DockWindow(WND *wndPtr)
976
977   int data = 1;
978   Window win = X11DRV_WND_GetXWindow(wndPtr);
979   if (kwmDockWindow == None) 
980           return; /* no KDE running */
981   TSXChangeProperty(
982     display,win,kwmDockWindow,kwmDockWindow,32,PropModeReplace,(char*)&data,1
983   );
984 }
985