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