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