Release 20000326.
[wine/gsoc-2012-control.git] / windows / x11drv / wnd.c
bloba991f3f254843808f10f2ac42b783b9a2d11f6bc
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 #ifndef X_DISPLAY_MISSING
13 #include <X11/Xatom.h>
14 #include "ts_xlib.h"
15 #include "ts_xutil.h"
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 "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;
585 /* Only mess with the X focus if there's */
586 /* no desktop window and if the window is not managed by the WM. */
587 if ((X11DRV_GetXRootWindow() != DefaultRootWindow(display))
588 || (wndPtr->flags & WIN_MANAGED)) return;
590 if (!hwnd) /* If setting the focus to 0, uninstall the colormap */
592 if (X11DRV_PALETTE_PaletteFlags & X11DRV_PALETTE_PRIVATE)
593 TSXUninstallColormap( display, X11DRV_PALETTE_PaletteXColormap );
594 return;
597 /* Set X focus and install colormap */
599 if (!(win = X11DRV_WND_FindXWindow(wndPtr))) return;
600 if (!TSXGetWindowAttributes( display, win, &win_attr ) ||
601 (win_attr.map_state != IsViewable))
602 return; /* If window is not viewable, don't change anything */
604 TSXSetInputFocus( display, win, RevertToParent, CurrentTime );
605 if (X11DRV_PALETTE_PaletteFlags & X11DRV_PALETTE_PRIVATE)
606 TSXInstallColormap( display, X11DRV_PALETTE_PaletteXColormap );
608 EVENT_Synchronize();
611 /*****************************************************************
612 * X11DRV_WND_PreSizeMove
614 void X11DRV_WND_PreSizeMove(WND *wndPtr)
616 if (!(wndPtr->dwStyle & WS_CHILD) && (X11DRV_GetXRootWindow() == DefaultRootWindow(display)))
617 TSXGrabServer( display );
620 /*****************************************************************
621 * X11DRV_WND_PostSizeMove
623 void X11DRV_WND_PostSizeMove(WND *wndPtr)
625 if (!(wndPtr->dwStyle & WS_CHILD) &&
626 (X11DRV_GetXRootWindow() == DefaultRootWindow(display)))
627 TSXUngrabServer( display );
630 /*****************************************************************
631 * X11DRV_WND_SurfaceCopy
633 * Copies rect to (rect.left + dx, rect.top + dy).
635 void X11DRV_WND_SurfaceCopy(WND* wndPtr, DC *dcPtr, INT dx, INT dy,
636 const RECT *rect, BOOL bUpdate)
638 X11DRV_PDEVICE *physDev = (X11DRV_PDEVICE *)dcPtr->physDev;
639 POINT dst, src;
641 dst.x = (src.x = dcPtr->w.DCOrgX + rect->left) + dx;
642 dst.y = (src.y = dcPtr->w.DCOrgY + rect->top) + dy;
644 if (bUpdate) /* handles non-Wine windows hanging over the copied area */
645 TSXSetGraphicsExposures( display, physDev->gc, True );
646 TSXSetFunction( display, physDev->gc, GXcopy );
647 TSXCopyArea( display, physDev->drawable, physDev->drawable,
648 physDev->gc, src.x, src.y,
649 rect->right - rect->left,
650 rect->bottom - rect->top,
651 dst.x, dst.y );
652 if (bUpdate)
653 TSXSetGraphicsExposures( display, physDev->gc, False );
655 if (bUpdate) /* Make sure exposure events have been processed */
656 EVENT_Synchronize();
659 /***********************************************************************
660 * X11DRV_WND_SetDrawable
662 * Set the drawable, origin and dimensions for the DC associated to
663 * a given window.
665 void X11DRV_WND_SetDrawable(WND *wndPtr, DC *dc, WORD flags, BOOL bSetClipOrigin)
667 X11DRV_PDEVICE *physDev = (X11DRV_PDEVICE *)dc->physDev;
668 INT dcOrgXCopy = 0, dcOrgYCopy = 0;
669 BOOL offsetClipRgn = FALSE;
671 if (!wndPtr) /* Get a DC for the whole screen */
673 dc->w.DCOrgX = 0;
674 dc->w.DCOrgY = 0;
675 physDev->drawable = X11DRV_GetXRootWindow();
676 TSXSetSubwindowMode( display, physDev->gc, IncludeInferiors );
678 else
681 * This function change the coordinate system (DCOrgX,DCOrgY)
682 * values. When it moves the origin, other data like the current clipping
683 * region will not be moved to that new origin. In the case of DCs that are class
684 * or window DCs that clipping region might be a valid value from a previous use
685 * of the DC and changing the origin of the DC without moving the clip region
686 * results in a clip region that is not placed properly in the DC.
687 * This code will save the dc origin, let the SetDrawable
688 * modify the origin and reset the clipping. When the clipping is set,
689 * it is moved according to the new DC origin.
691 if ( (wndPtr->class->style & (CS_OWNDC | CS_CLASSDC)) && (dc->w.hClipRgn > 0))
693 dcOrgXCopy = dc->w.DCOrgX;
694 dcOrgYCopy = dc->w.DCOrgY;
695 offsetClipRgn = TRUE;
698 if (flags & DCX_WINDOW)
700 dc->w.DCOrgX = wndPtr->rectWindow.left;
701 dc->w.DCOrgY = wndPtr->rectWindow.top;
703 else
705 dc->w.DCOrgX = wndPtr->rectClient.left;
706 dc->w.DCOrgY = wndPtr->rectClient.top;
708 while (!X11DRV_WND_GetXWindow(wndPtr))
710 wndPtr = wndPtr->parent;
711 dc->w.DCOrgX += wndPtr->rectClient.left;
712 dc->w.DCOrgY += wndPtr->rectClient.top;
714 dc->w.DCOrgX -= wndPtr->rectWindow.left;
715 dc->w.DCOrgY -= wndPtr->rectWindow.top;
717 /* reset the clip region, according to the new origin */
718 if ( offsetClipRgn )
720 OffsetRgn(dc->w.hClipRgn, dc->w.DCOrgX - dcOrgXCopy,dc->w.DCOrgY - dcOrgYCopy);
723 physDev->drawable = X11DRV_WND_GetXWindow(wndPtr);
725 #if 0
726 /* This is needed when we reuse a cached DC because
727 * SetDCState() called by ReleaseDC() screws up DC
728 * origins for child windows.
731 if( bSetClipOrigin )
732 TSXSetClipOrigin( display, physDev->gc, dc->w.DCOrgX, dc->w.DCOrgY );
733 #endif
737 /***********************************************************************
738 * X11DRV_SetWMHint
740 static BOOL X11DRV_SetWMHint(Display* display, WND* wndPtr, int hint, int val)
742 XWMHints* wm_hints = TSXAllocWMHints();
744 wm_hints->flags = hint;
745 switch( hint )
747 case InputHint:
748 wm_hints->input = val;
749 break;
751 case StateHint:
752 wm_hints->initial_state = val;
753 break;
755 case IconPixmapHint:
756 wm_hints->icon_pixmap = (Pixmap)val;
757 break;
759 case IconWindowHint:
760 wm_hints->icon_window = (Window)val;
761 break;
764 TSXSetWMHints( display, X11DRV_WND_GetXWindow(wndPtr), wm_hints );
765 TSXFree(wm_hints);
766 return TRUE;
768 return FALSE;
772 /***********************************************************************
773 * X11DRV_WND_SetHostAttr
775 * This function returns TRUE if the attribute is supported and the
776 * action was successful. Otherwise it should return FALSE and Wine will try
777 * to get by without the functionality provided by the host window system.
779 BOOL X11DRV_WND_SetHostAttr(WND* wnd, INT ha, INT value)
781 Window w;
783 if( (w = X11DRV_WND_GetXWindow(wnd)) )
785 XSetWindowAttributes win_attr;
787 switch( ha )
789 case HAK_ICONICSTATE: /* called when a window is minimized/restored */
791 if( (wnd->flags & WIN_MANAGED) )
793 if( value )
795 if( wnd->dwStyle & WS_VISIBLE )
797 XClientMessageEvent ev;
799 /* FIXME: set proper icon */
801 ev.type = ClientMessage;
802 ev.display = display;
803 ev.message_type = wmChangeState;
804 ev.format = 32;
805 ev.data.l[0] = IconicState;
806 ev.window = w;
808 if( TSXSendEvent (display,
809 RootWindow( display, XScreenNumberOfScreen(X11DRV_GetXScreen()) ),
810 True, (SubstructureRedirectMask | SubstructureNotifyMask), (XEvent*)&ev))
812 XEvent xe;
813 TSXFlush (display);
814 while( !TSXCheckTypedWindowEvent( display, w, UnmapNotify, &xe) );
816 else
817 break;
819 else
820 X11DRV_SetWMHint( display, wnd, StateHint, IconicState );
822 else
824 if( !(wnd->flags & WS_VISIBLE) )
825 X11DRV_SetWMHint( display, wnd, StateHint, NormalState );
826 else
828 XEvent xe;
829 TSXMapWindow(display, w );
830 while( !TSXCheckTypedWindowEvent( display, w, MapNotify, &xe) );
833 return TRUE;
835 break;
837 case HAK_BITGRAVITY: /* called when a window is resized */
839 if( ((X11DRV_WND_DATA *) wnd->pDriverData)->bit_gravity != value )
841 win_attr.bit_gravity = value;
842 ((X11DRV_WND_DATA *) wnd->pDriverData)->bit_gravity = value;
843 TSXChangeWindowAttributes( display, w, CWBitGravity, &win_attr );
845 return TRUE;
847 case HAK_ACCEPTFOCUS: /* called when a window is disabled/enabled */
849 if( (wnd->flags & WIN_MANAGED) )
850 return X11DRV_SetWMHint( display, wnd, InputHint, value );
853 return FALSE;
856 /***********************************************************************
857 * X11DRV_WND_IsSelfClipping
859 BOOL X11DRV_WND_IsSelfClipping(WND *wndPtr)
861 return X11DRV_WND_GetXWindow(wndPtr) != None;
864 /***********************************************************************
865 * X11DRV_WND_DockWindow
867 * Set the X Property of the window that tells the windowmanager we really
868 * want to be in the systray
870 * KDE: set "KWM_DOCKWINDOW", type "KWM_DOCKWINDOW" to 1 before a window is
871 * mapped.
873 * all others: to be added ;)
875 void X11DRV_WND_DockWindow(WND *wndPtr)
877 int data = 1;
878 Window win = X11DRV_WND_GetXWindow(wndPtr);
879 if (kwmDockWindow == None)
880 return; /* no KDE running */
881 TSXChangeProperty(
882 display,win,kwmDockWindow,kwmDockWindow,32,PropModeReplace,(char*)&data,1
885 #endif /* !defined(X_DISPLAY_MISSING) */