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