X11DRV_SetFocus: really don't mess with focus for managed windows.
[wine.git] / windows / x11drv / wnd.c
blob58858d7c6d84f0cd394562c14e6e8fd8bb9822cc
1 /*
2 * X11 windows driver
4 * Copyright 1993, 1994, 1995, 1996 Alexandre Julliard
5 * 1993 David Metcalfe
6 * 1995, 1996 Alex Korobka
7 */
9 #include "config.h"
11 #include <X11/Xatom.h>
13 #include "ts_xlib.h"
14 #include "ts_xutil.h"
16 #include <stdlib.h>
17 #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 "wingdi.h"
32 #include "wine/winuser16.h"
34 DEFAULT_DEBUG_CHANNEL(win)
36 /* Some useful macros */
37 #define HAS_DLGFRAME(style,exStyle) \
38 ((!((style) & WS_THICKFRAME)) && (((style) & WS_DLGFRAME) || ((exStyle) & WS_EX_DLGMODALFRAME)))
40 /**********************************************************************/
42 extern Cursor X11DRV_MOUSE_XCursor; /* Current X cursor */
43 extern BOOL X11DRV_CreateBitmap( HBITMAP );
44 extern Pixmap X11DRV_BITMAP_Pixmap( HBITMAP );
46 /**********************************************************************/
48 /* X context to associate a hwnd to an X window */
49 XContext winContext = 0;
51 Atom wmProtocols = None;
52 Atom wmDeleteWindow = None;
53 Atom dndProtocol = None;
54 Atom dndSelection = None;
55 Atom wmChangeState = None;
57 Atom kwmDockWindow = None;
59 /***********************************************************************
60 * X11DRV_WND_GetXWindow
62 * Return the X window associated to a window.
64 Window X11DRV_WND_GetXWindow(WND *wndPtr)
66 return wndPtr && wndPtr->pDriverData ?
67 ((X11DRV_WND_DATA *) wndPtr->pDriverData)->window : 0;
70 /***********************************************************************
71 * X11DRV_WND_FindXWindow
73 * Return the the first X window associated to a window chain.
75 Window X11DRV_WND_FindXWindow(WND *wndPtr)
77 while (wndPtr &&
78 !((X11DRV_WND_DATA *) wndPtr->pDriverData)->window)
79 wndPtr = wndPtr->parent;
80 return wndPtr ?
81 ((X11DRV_WND_DATA *) wndPtr->pDriverData)->window : 0;
84 /***********************************************************************
85 * X11DRV_WND_RegisterWindow
87 * Associate an X window to a HWND.
89 static void X11DRV_WND_RegisterWindow(WND *wndPtr)
91 TSXSetWMProtocols( display, X11DRV_WND_GetXWindow(wndPtr), &wmDeleteWindow, 1 );
93 if (!winContext) winContext = TSXUniqueContext();
94 TSXSaveContext( display, X11DRV_WND_GetXWindow(wndPtr),
95 winContext, (char *) wndPtr->hwndSelf );
98 /**********************************************************************
99 * X11DRV_WND_Initialize
101 void X11DRV_WND_Initialize(WND *wndPtr)
103 X11DRV_WND_DATA *pWndDriverData =
104 (X11DRV_WND_DATA *) HeapAlloc(SystemHeap, 0, sizeof(X11DRV_WND_DATA));
106 wndPtr->pDriverData = (void *) pWndDriverData;
108 pWndDriverData->window = 0;
111 /**********************************************************************
112 * X11DRV_WND_Finalize
114 void X11DRV_WND_Finalize(WND *wndPtr)
116 X11DRV_WND_DATA *pWndDriverData =
117 (X11DRV_WND_DATA *) wndPtr->pDriverData;
119 if (!wndPtr->pDriverData) {
120 ERR("Trying to destroy window again. Not good.\n");
121 return;
123 if(pWndDriverData->window)
125 ERR(
126 "WND destroyed without destroying "
127 "the associated X Window (%ld)\n",
128 pWndDriverData->window
131 HeapFree(SystemHeap, 0, wndPtr->pDriverData);
132 wndPtr->pDriverData = NULL;
135 /**********************************************************************
136 * X11DRV_WND_CreateDesktopWindow
138 BOOL X11DRV_WND_CreateDesktopWindow(WND *wndPtr, CLASS *classPtr, BOOL bUnicode)
140 if (wmProtocols == None)
141 wmProtocols = TSXInternAtom( display, "WM_PROTOCOLS", True );
142 if (wmDeleteWindow == None)
143 wmDeleteWindow = TSXInternAtom( display, "WM_DELETE_WINDOW", True );
144 if( dndProtocol == None )
145 dndProtocol = TSXInternAtom( display, "DndProtocol" , False );
146 if( dndSelection == None )
147 dndSelection = TSXInternAtom( display, "DndSelection" , False );
148 if( wmChangeState == None )
149 wmChangeState = TSXInternAtom (display, "WM_CHANGE_STATE", False);
150 if (kwmDockWindow == None)
151 kwmDockWindow = TSXInternAtom( display, "KWM_DOCKWINDOW", False );
153 ((X11DRV_WND_DATA *) wndPtr->pDriverData)->window = X11DRV_GetXRootWindow();
154 X11DRV_WND_RegisterWindow( wndPtr );
156 return TRUE;
160 /**********************************************************************
161 * X11DRV_WND_CreateWindow
163 BOOL X11DRV_WND_CreateWindow(WND *wndPtr, CLASS *classPtr, CREATESTRUCTA *cs, BOOL bUnicode)
165 /* Create the X window (only for top-level windows, and then only */
166 /* when there's no desktop window) */
168 if (!(cs->style & WS_CHILD) && (X11DRV_GetXRootWindow() == DefaultRootWindow(display)))
170 Window wGroupLeader;
171 XWMHints* wm_hints;
172 XSetWindowAttributes win_attr;
174 /* Create "managed" windows only if a title bar or resizable */
175 /* frame is required. */
176 if (WIN_WindowNeedsWMBorder(cs->style, cs->dwExStyle)) {
177 win_attr.event_mask = ExposureMask | KeyPressMask |
178 KeyReleaseMask | PointerMotionMask |
179 ButtonPressMask | ButtonReleaseMask |
180 FocusChangeMask | StructureNotifyMask;
181 win_attr.override_redirect = FALSE;
182 wndPtr->flags |= WIN_MANAGED;
183 } else {
184 win_attr.event_mask = ExposureMask | KeyPressMask |
185 KeyReleaseMask | PointerMotionMask |
186 ButtonPressMask | ButtonReleaseMask |
187 FocusChangeMask;
188 win_attr.override_redirect = TRUE;
190 wndPtr->flags |= WIN_NATIVE;
192 win_attr.bit_gravity = (classPtr->style & (CS_VREDRAW | CS_HREDRAW)) ? BGForget : BGNorthWest;
193 win_attr.colormap = X11DRV_PALETTE_PaletteXColormap;
194 win_attr.backing_store = NotUseful;
195 win_attr.save_under = ((classPtr->style & CS_SAVEBITS) != 0);
196 win_attr.cursor = X11DRV_MOUSE_XCursor;
198 ((X11DRV_WND_DATA *) wndPtr->pDriverData)->hWMIconBitmap = 0;
199 ((X11DRV_WND_DATA *) wndPtr->pDriverData)->bit_gravity = win_attr.bit_gravity;
200 ((X11DRV_WND_DATA *) wndPtr->pDriverData)->window =
201 TSXCreateWindow( display, X11DRV_GetXRootWindow(),
202 cs->x, cs->y, cs->cx, cs->cy,
203 0, CopyFromParent,
204 InputOutput, CopyFromParent,
205 CWEventMask | CWOverrideRedirect |
206 CWColormap | CWCursor | CWSaveUnder |
207 CWBackingStore | CWBitGravity,
208 &win_attr );
210 if(!(wGroupLeader = X11DRV_WND_GetXWindow(wndPtr)))
211 return FALSE;
213 /* If we are the systray, we need to be managed to be noticed by KWM */
215 if (wndPtr->dwExStyle & WS_EX_TRAYWINDOW)
216 X11DRV_WND_DockWindow(wndPtr);
218 if (wndPtr->flags & WIN_MANAGED)
220 XClassHint *class_hints = TSXAllocClassHint();
221 XSizeHints* size_hints = TSXAllocSizeHints();
223 if (class_hints)
225 class_hints->res_name = "wineManaged";
226 class_hints->res_class = "Wine";
227 TSXSetClassHint( display, ((X11DRV_WND_DATA *) wndPtr->pDriverData)->window, class_hints );
228 TSXFree (class_hints);
231 if (size_hints)
233 size_hints->win_gravity = StaticGravity;
234 size_hints->flags = PWinGravity;
236 if (HAS_DLGFRAME(cs->style,cs->dwExStyle))
238 size_hints->min_width = size_hints->max_width = cs->cx;
239 size_hints->min_height = size_hints->max_height = cs->cy;
240 size_hints->flags |= PMinSize | PMaxSize;
243 TSXSetWMSizeHints( display, X11DRV_WND_GetXWindow(wndPtr),
244 size_hints, XA_WM_NORMAL_HINTS );
245 TSXFree(size_hints);
249 if (cs->hwndParent) /* Get window owner */
251 Window w;
252 WND *tmpWnd = WIN_FindWndPtr(cs->hwndParent);
254 w = X11DRV_WND_FindXWindow( tmpWnd );
255 if (w != None)
257 TSXSetTransientForHint( display, X11DRV_WND_GetXWindow(wndPtr), w );
258 wGroupLeader = w;
260 WIN_ReleaseWndPtr(tmpWnd);
263 wm_hints = TSXAllocWMHints();
265 wm_hints->flags = InputHint | StateHint | WindowGroupHint;
266 wm_hints->input = True;
268 if( wndPtr->flags & WIN_MANAGED )
270 if( wndPtr->class->hIcon )
272 CURSORICONINFO *ptr;
274 if( (ptr = (CURSORICONINFO *)GlobalLock16( wndPtr->class->hIcon )) )
276 /* This is not entirely correct, may need to create
277 * an icon window and set the pixmap as a background */
279 HBITMAP hBitmap = CreateBitmap( ptr->nWidth, ptr->nHeight,
280 ptr->bPlanes, ptr->bBitsPerPixel, (char *)(ptr + 1) +
281 ptr->nHeight * BITMAP_GetWidthBytes(ptr->nWidth,1) );
283 if( hBitmap )
285 ((X11DRV_WND_DATA *) wndPtr->pDriverData)->hWMIconBitmap = hBitmap;
286 X11DRV_CreateBitmap( hBitmap );
287 wm_hints->flags |= IconPixmapHint;
288 wm_hints->icon_pixmap = X11DRV_BITMAP_Pixmap( hBitmap );
292 wm_hints->initial_state = (wndPtr->dwStyle & WS_MINIMIZE)
293 ? IconicState : NormalState;
295 else
296 wm_hints->initial_state = NormalState;
297 wm_hints->window_group = wGroupLeader;
299 TSXSetWMHints( display, X11DRV_WND_GetXWindow(wndPtr), wm_hints );
300 TSXFree(wm_hints);
302 X11DRV_WND_RegisterWindow( wndPtr );
304 return TRUE;
307 /***********************************************************************
308 * X11DRV_WND_DestroyWindow
310 BOOL X11DRV_WND_DestroyWindow(WND *wndPtr)
312 Window w;
313 if ((w = X11DRV_WND_GetXWindow(wndPtr)))
315 XEvent xe;
316 TSXDeleteContext( display, w, winContext );
317 TSXDestroyWindow( display, w );
318 while( TSXCheckWindowEvent(display, w, NoEventMask, &xe) );
320 ((X11DRV_WND_DATA *) wndPtr->pDriverData)->window = None;
321 if( ((X11DRV_WND_DATA *) wndPtr->pDriverData)->hWMIconBitmap )
323 DeleteObject( ((X11DRV_WND_DATA *) wndPtr->pDriverData)->hWMIconBitmap );
324 ((X11DRV_WND_DATA *) wndPtr->pDriverData)->hWMIconBitmap = 0;
328 return TRUE;
331 /*****************************************************************
332 * X11DRV_WND_SetParent
334 WND *X11DRV_WND_SetParent(WND *wndPtr, WND *pWndParent)
336 WND *pDesktop = WIN_GetDesktop();
338 if( wndPtr && pWndParent && (wndPtr != pDesktop) )
340 WND* pWndPrev = wndPtr->parent;
342 if( pWndParent != pWndPrev )
344 if ( X11DRV_WND_GetXWindow(wndPtr) )
346 /* Toplevel window needs to be reparented. Used by Tk 8.0 */
348 TSXDestroyWindow( display, X11DRV_WND_GetXWindow(wndPtr) );
349 ((X11DRV_WND_DATA *) wndPtr->pDriverData)->window = None;
352 WIN_UnlinkWindow(wndPtr->hwndSelf);
353 wndPtr->parent = pWndParent;
355 /* Create an X counterpart for reparented top-level windows
356 * when not in the desktop mode. */
358 if( pWndParent == pDesktop )
360 wndPtr->dwStyle &= ~WS_CHILD;
361 wndPtr->wIDmenu = 0;
362 if( X11DRV_GetXRootWindow() == DefaultRootWindow(display) )
364 CREATESTRUCTA cs;
365 cs.lpCreateParams = NULL;
366 cs.hInstance = 0; /* not used in following call */
367 cs.hMenu = 0; /* not used in following call */
368 cs.hwndParent = pWndParent->hwndSelf;
369 cs.cy = wndPtr->rectWindow.bottom - wndPtr->rectWindow.top;
370 if (!cs.cy)
371 cs.cy = 1;
372 cs.cx = wndPtr->rectWindow.right - wndPtr->rectWindow.left;
373 if (!cs.cx)
374 cs.cx = 1;
375 cs.y = wndPtr->rectWindow.top;
376 cs.x = wndPtr->rectWindow.left;
377 cs.style = wndPtr->dwStyle;
378 cs.lpszName = 0; /* not used in following call */
379 cs.lpszClass = 0; /*not used in following call */
380 cs.dwExStyle = wndPtr->dwExStyle;
381 X11DRV_WND_CreateWindow(wndPtr, wndPtr->class,
382 &cs, FALSE);
385 else /* a child window */
387 if( !( wndPtr->dwStyle & WS_CHILD ) )
389 wndPtr->dwStyle |= WS_CHILD;
390 if( wndPtr->wIDmenu != 0)
392 DestroyMenu( (HMENU) wndPtr->wIDmenu );
393 wndPtr->wIDmenu = 0;
397 WIN_LinkWindow(wndPtr->hwndSelf, HWND_TOP);
399 WIN_ReleaseDesktop();
400 return pWndPrev;
401 } /* failure */
402 WIN_ReleaseDesktop();
403 return 0;
406 /***********************************************************************
407 * X11DRV_WND_ForceWindowRaise
409 * Raise a window on top of the X stacking order, while preserving
410 * the correct Windows Z order.
412 void X11DRV_WND_ForceWindowRaise(WND *wndPtr)
414 XWindowChanges winChanges;
415 WND *wndPrev,*pDesktop = WIN_GetDesktop();
417 if( !wndPtr || !X11DRV_WND_GetXWindow(wndPtr) || (wndPtr->flags & WIN_MANAGED) )
419 WIN_ReleaseDesktop();
420 return;
423 /* Raise all windows up to wndPtr according to their Z order.
424 * (it would be easier with sibling-related Below but it doesn't
425 * work very well with SGI mwm for instance)
427 winChanges.stack_mode = Above;
428 while (wndPtr)
430 if (X11DRV_WND_GetXWindow(wndPtr))
431 TSXReconfigureWMWindow( display, X11DRV_WND_GetXWindow(wndPtr), 0,
432 CWStackMode, &winChanges );
433 wndPrev = pDesktop->child;
434 if (wndPrev == wndPtr) break;
435 while (wndPrev && (wndPrev->next != wndPtr)) wndPrev = wndPrev->next;
436 wndPtr = wndPrev;
438 WIN_ReleaseDesktop();
441 /***********************************************************************
442 * X11DRV_WND_FindDesktopXWindow [Internal]
444 * Find the actual X window which needs be restacked.
445 * Used by X11DRV_WND_SetWindowPos().
447 static Window X11DRV_WND_FindDesktopXWindow( WND *wndPtr )
449 if (!(wndPtr->flags & WIN_MANAGED))
450 return X11DRV_WND_GetXWindow(wndPtr);
451 else
453 Window window, root, parent, *children;
454 int nchildren;
455 window = X11DRV_WND_GetXWindow(wndPtr);
456 for (;;)
458 TSXQueryTree( display, window, &root, &parent,
459 &children, &nchildren );
460 TSXFree( children );
461 if (parent == root)
462 return window;
463 window = parent;
468 /***********************************************************************
469 * WINPOS_SetXWindowPos
471 * SetWindowPos() for an X window. Used by the real SetWindowPos().
473 void X11DRV_WND_SetWindowPos(WND *wndPtr, const WINDOWPOS *winpos, BOOL bChangePos)
475 XWindowChanges winChanges;
476 int changeMask = 0;
477 WND *winposPtr = WIN_FindWndPtr( winpos->hwnd );
478 if ( !winposPtr ) return;
480 if(!wndPtr->hwndSelf) wndPtr = NULL; /* FIXME: WND destroyed, shouldn't happen!!! */
482 if (!(winpos->flags & SWP_SHOWWINDOW) && (winpos->flags & SWP_HIDEWINDOW))
484 if(X11DRV_WND_GetXWindow(wndPtr))
485 TSXUnmapWindow( display, X11DRV_WND_GetXWindow(wndPtr) );
488 if(bChangePos)
490 if ( !(winpos->flags & SWP_NOSIZE))
492 winChanges.width = (winpos->cx > 0 ) ? winpos->cx : 1;
493 winChanges.height = (winpos->cy > 0 ) ? winpos->cy : 1;
494 changeMask |= CWWidth | CWHeight;
496 /* Tweak dialog window size hints */
498 if ((winposPtr->flags & WIN_MANAGED) &&
499 HAS_DLGFRAME(winposPtr->dwStyle,winposPtr->dwExStyle))
501 XSizeHints *size_hints = TSXAllocSizeHints();
503 if (size_hints)
505 long supplied_return;
507 TSXGetWMSizeHints( display, X11DRV_WND_GetXWindow(winposPtr), size_hints,
508 &supplied_return, XA_WM_NORMAL_HINTS);
509 size_hints->min_width = size_hints->max_width = winpos->cx;
510 size_hints->min_height = size_hints->max_height = winpos->cy;
511 TSXSetWMSizeHints( display, X11DRV_WND_GetXWindow(winposPtr), size_hints,
512 XA_WM_NORMAL_HINTS );
513 TSXFree(size_hints);
517 if (!(winpos->flags & SWP_NOMOVE))
519 winChanges.x = winpos->x;
520 winChanges.y = winpos->y;
521 changeMask |= CWX | CWY;
523 if (!(winpos->flags & SWP_NOZORDER))
525 winChanges.stack_mode = Below;
526 changeMask |= CWStackMode;
528 if (winpos->hwndInsertAfter == HWND_TOP) winChanges.stack_mode = Above;
529 else if (winpos->hwndInsertAfter != HWND_BOTTOM)
531 WND* insertPtr = WIN_FindWndPtr( winpos->hwndInsertAfter );
532 Window stack[2];
534 stack[0] = X11DRV_WND_FindDesktopXWindow( insertPtr );
535 stack[1] = X11DRV_WND_FindDesktopXWindow( winposPtr );
537 /* for stupid window managers (i.e. all of them) */
539 TSXRestackWindows(display, stack, 2);
540 changeMask &= ~CWStackMode;
542 WIN_ReleaseWndPtr(insertPtr);
545 if (changeMask && X11DRV_WND_GetXWindow(winposPtr))
547 TSXReconfigureWMWindow( display, X11DRV_WND_GetXWindow(winposPtr), 0, changeMask, &winChanges );
548 if( winposPtr->class->style & (CS_VREDRAW | CS_HREDRAW) )
549 X11DRV_WND_SetHostAttr( winposPtr, HAK_BITGRAVITY, BGForget );
553 if ( winpos->flags & SWP_SHOWWINDOW )
555 if(X11DRV_WND_GetXWindow(wndPtr))
556 TSXMapWindow( display, X11DRV_WND_GetXWindow(wndPtr) );
558 WIN_ReleaseWndPtr(winposPtr);
561 /*****************************************************************
562 * X11DRV_WND_SetText
564 void X11DRV_WND_SetText(WND *wndPtr, LPCSTR text)
566 if (!X11DRV_WND_GetXWindow(wndPtr))
567 return;
569 TSXStoreName( display, X11DRV_WND_GetXWindow(wndPtr), text );
570 TSXSetIconName( display, X11DRV_WND_GetXWindow(wndPtr), text );
573 /*****************************************************************
574 * X11DRV_WND_SetFocus
576 * Set the X focus.
577 * Explicit colormap management seems to work only with OLVWM.
579 void X11DRV_WND_SetFocus(WND *wndPtr)
581 HWND hwnd = wndPtr->hwndSelf;
582 XWindowAttributes win_attr;
583 Window win;
584 WND *w = wndPtr;
586 /* Only mess with the X focus if there's */
587 /* no desktop window and if the window is not managed by the WM. */
588 if ((X11DRV_GetXRootWindow() != DefaultRootWindow(display))) return;
589 while (w && !((X11DRV_WND_DATA *) w->pDriverData)->window)
590 w = w->parent;
591 if (!w) w = wndPtr;
592 if (w->flags & WIN_MANAGED) return;
594 if (!hwnd) /* If setting the focus to 0, uninstall the colormap */
596 if (X11DRV_PALETTE_PaletteFlags & X11DRV_PALETTE_PRIVATE)
597 TSXUninstallColormap( display, X11DRV_PALETTE_PaletteXColormap );
598 return;
601 /* Set X focus and install colormap */
603 if (!(win = X11DRV_WND_FindXWindow(wndPtr))) return;
604 if (!TSXGetWindowAttributes( display, win, &win_attr ) ||
605 (win_attr.map_state != IsViewable))
606 return; /* If window is not viewable, don't change anything */
608 TSXSetInputFocus( display, win, RevertToParent, CurrentTime );
609 if (X11DRV_PALETTE_PaletteFlags & X11DRV_PALETTE_PRIVATE)
610 TSXInstallColormap( display, X11DRV_PALETTE_PaletteXColormap );
612 EVENT_Synchronize();
615 /*****************************************************************
616 * X11DRV_WND_PreSizeMove
618 void X11DRV_WND_PreSizeMove(WND *wndPtr)
620 if (!(wndPtr->dwStyle & WS_CHILD) && (X11DRV_GetXRootWindow() == DefaultRootWindow(display)))
621 TSXGrabServer( display );
624 /*****************************************************************
625 * X11DRV_WND_PostSizeMove
627 void X11DRV_WND_PostSizeMove(WND *wndPtr)
629 if (!(wndPtr->dwStyle & WS_CHILD) &&
630 (X11DRV_GetXRootWindow() == DefaultRootWindow(display)))
631 TSXUngrabServer( display );
634 /*****************************************************************
635 * X11DRV_WND_SurfaceCopy
637 * Copies rect to (rect.left + dx, rect.top + dy).
639 void X11DRV_WND_SurfaceCopy(WND* wndPtr, DC *dcPtr, INT dx, INT dy,
640 const RECT *rect, BOOL bUpdate)
642 X11DRV_PDEVICE *physDev = (X11DRV_PDEVICE *)dcPtr->physDev;
643 POINT dst, src;
645 dst.x = (src.x = dcPtr->w.DCOrgX + rect->left) + dx;
646 dst.y = (src.y = dcPtr->w.DCOrgY + rect->top) + dy;
648 if (bUpdate) /* handles non-Wine windows hanging over the copied area */
649 TSXSetGraphicsExposures( display, physDev->gc, True );
650 TSXSetFunction( display, physDev->gc, GXcopy );
651 TSXCopyArea( display, physDev->drawable, physDev->drawable,
652 physDev->gc, src.x, src.y,
653 rect->right - rect->left,
654 rect->bottom - rect->top,
655 dst.x, dst.y );
656 if (bUpdate)
657 TSXSetGraphicsExposures( display, physDev->gc, False );
659 if (bUpdate) /* Make sure exposure events have been processed */
660 EVENT_Synchronize();
663 /***********************************************************************
664 * X11DRV_WND_SetDrawable
666 * Set the drawable, origin and dimensions for the DC associated to
667 * a given window.
669 void X11DRV_WND_SetDrawable(WND *wndPtr, DC *dc, WORD flags, BOOL bSetClipOrigin)
671 X11DRV_PDEVICE *physDev = (X11DRV_PDEVICE *)dc->physDev;
672 INT dcOrgXCopy = 0, dcOrgYCopy = 0;
673 BOOL offsetClipRgn = FALSE;
675 if (!wndPtr) /* Get a DC for the whole screen */
677 dc->w.DCOrgX = 0;
678 dc->w.DCOrgY = 0;
679 physDev->drawable = X11DRV_GetXRootWindow();
680 TSXSetSubwindowMode( display, physDev->gc, IncludeInferiors );
682 else
685 * This function change the coordinate system (DCOrgX,DCOrgY)
686 * values. When it moves the origin, other data like the current clipping
687 * region will not be moved to that new origin. In the case of DCs that are class
688 * or window DCs that clipping region might be a valid value from a previous use
689 * of the DC and changing the origin of the DC without moving the clip region
690 * results in a clip region that is not placed properly in the DC.
691 * This code will save the dc origin, let the SetDrawable
692 * modify the origin and reset the clipping. When the clipping is set,
693 * it is moved according to the new DC origin.
695 if ( (wndPtr->class->style & (CS_OWNDC | CS_CLASSDC)) && (dc->w.hClipRgn > 0))
697 dcOrgXCopy = dc->w.DCOrgX;
698 dcOrgYCopy = dc->w.DCOrgY;
699 offsetClipRgn = TRUE;
702 if (flags & DCX_WINDOW)
704 dc->w.DCOrgX = wndPtr->rectWindow.left;
705 dc->w.DCOrgY = wndPtr->rectWindow.top;
707 else
709 dc->w.DCOrgX = wndPtr->rectClient.left;
710 dc->w.DCOrgY = wndPtr->rectClient.top;
712 while (!X11DRV_WND_GetXWindow(wndPtr))
714 wndPtr = wndPtr->parent;
715 dc->w.DCOrgX += wndPtr->rectClient.left;
716 dc->w.DCOrgY += wndPtr->rectClient.top;
718 dc->w.DCOrgX -= wndPtr->rectWindow.left;
719 dc->w.DCOrgY -= wndPtr->rectWindow.top;
721 /* reset the clip region, according to the new origin */
722 if ( offsetClipRgn )
724 OffsetRgn(dc->w.hClipRgn, dc->w.DCOrgX - dcOrgXCopy,dc->w.DCOrgY - dcOrgYCopy);
727 physDev->drawable = X11DRV_WND_GetXWindow(wndPtr);
729 #if 0
730 /* This is needed when we reuse a cached DC because
731 * SetDCState() called by ReleaseDC() screws up DC
732 * origins for child windows.
735 if( bSetClipOrigin )
736 TSXSetClipOrigin( display, physDev->gc, dc->w.DCOrgX, dc->w.DCOrgY );
737 #endif
741 /***********************************************************************
742 * X11DRV_SetWMHint
744 static BOOL X11DRV_SetWMHint(Display* display, WND* wndPtr, int hint, int val)
746 XWMHints* wm_hints = TSXAllocWMHints();
748 wm_hints->flags = hint;
749 switch( hint )
751 case InputHint:
752 wm_hints->input = val;
753 break;
755 case StateHint:
756 wm_hints->initial_state = val;
757 break;
759 case IconPixmapHint:
760 wm_hints->icon_pixmap = (Pixmap)val;
761 break;
763 case IconWindowHint:
764 wm_hints->icon_window = (Window)val;
765 break;
768 TSXSetWMHints( display, X11DRV_WND_GetXWindow(wndPtr), wm_hints );
769 TSXFree(wm_hints);
770 return TRUE;
772 return FALSE;
776 /***********************************************************************
777 * X11DRV_WND_SetHostAttr
779 * This function returns TRUE if the attribute is supported and the
780 * action was successful. Otherwise it should return FALSE and Wine will try
781 * to get by without the functionality provided by the host window system.
783 BOOL X11DRV_WND_SetHostAttr(WND* wnd, INT ha, INT value)
785 Window w;
787 if( (w = X11DRV_WND_GetXWindow(wnd)) )
789 XSetWindowAttributes win_attr;
791 switch( ha )
793 case HAK_ICONICSTATE: /* called when a window is minimized/restored */
795 if( (wnd->flags & WIN_MANAGED) )
797 if( value )
799 if( wnd->dwStyle & WS_VISIBLE )
801 XClientMessageEvent ev;
803 /* FIXME: set proper icon */
805 ev.type = ClientMessage;
806 ev.display = display;
807 ev.message_type = wmChangeState;
808 ev.format = 32;
809 ev.data.l[0] = IconicState;
810 ev.window = w;
812 if( TSXSendEvent (display,
813 RootWindow( display, XScreenNumberOfScreen(X11DRV_GetXScreen()) ),
814 True, (SubstructureRedirectMask | SubstructureNotifyMask), (XEvent*)&ev))
816 XEvent xe;
817 TSXFlush (display);
818 while( !TSXCheckTypedWindowEvent( display, w, UnmapNotify, &xe) );
820 else
821 break;
823 else
824 X11DRV_SetWMHint( display, wnd, StateHint, IconicState );
826 else
828 if( !(wnd->flags & WS_VISIBLE) )
829 X11DRV_SetWMHint( display, wnd, StateHint, NormalState );
830 else
832 XEvent xe;
833 TSXMapWindow(display, w );
834 while( !TSXCheckTypedWindowEvent( display, w, MapNotify, &xe) );
837 return TRUE;
839 break;
841 case HAK_BITGRAVITY: /* called when a window is resized */
843 if( ((X11DRV_WND_DATA *) wnd->pDriverData)->bit_gravity != value )
845 win_attr.bit_gravity = value;
846 ((X11DRV_WND_DATA *) wnd->pDriverData)->bit_gravity = value;
847 TSXChangeWindowAttributes( display, w, CWBitGravity, &win_attr );
849 return TRUE;
851 case HAK_ACCEPTFOCUS: /* called when a window is disabled/enabled */
853 if( (wnd->flags & WIN_MANAGED) )
854 return X11DRV_SetWMHint( display, wnd, InputHint, value );
857 return FALSE;
860 /***********************************************************************
861 * X11DRV_WND_IsSelfClipping
863 BOOL X11DRV_WND_IsSelfClipping(WND *wndPtr)
865 return X11DRV_WND_GetXWindow(wndPtr) != None;
868 /***********************************************************************
869 * X11DRV_WND_DockWindow
871 * Set the X Property of the window that tells the windowmanager we really
872 * want to be in the systray
874 * KDE: set "KWM_DOCKWINDOW", type "KWM_DOCKWINDOW" to 1 before a window is
875 * mapped.
877 * all others: to be added ;)
879 void X11DRV_WND_DockWindow(WND *wndPtr)
881 int data = 1;
882 Window win = X11DRV_WND_GetXWindow(wndPtr);
883 if (kwmDockWindow == None)
884 return; /* no KDE running */
885 TSXChangeProperty(
886 display,win,kwmDockWindow,kwmDockWindow,32,PropModeReplace,(char*)&data,1