Removed some unnecessary #includes and dll dependencies.
[wine/multimedia.git] / windows / x11drv / wnd.c
blob3a4c1d88dbee9d0f2c9579176a712d90142806d5
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"
15 #include "ts_shape.h"
17 #include <stdlib.h>
18 #include <string.h>
20 #include "bitmap.h"
21 #include "debugtools.h"
22 #include "dce.h"
23 #include "dc.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 "winnls.h"
33 #include "wine/winuser16.h"
35 DEFAULT_DEBUG_CHANNEL(win);
37 /* Some useful macros */
38 #define HAS_DLGFRAME(style,exStyle) \
39 ((!((style) & WS_THICKFRAME)) && (((style) & WS_DLGFRAME) || ((exStyle) & WS_EX_DLGMODALFRAME)))
41 /**********************************************************************/
43 extern Cursor X11DRV_MOUSE_XCursor; /* Current X cursor */
44 extern BOOL X11DRV_CreateBitmap( HBITMAP );
45 extern Pixmap X11DRV_BITMAP_Pixmap( HBITMAP );
47 /**********************************************************************/
49 /* X context to associate a hwnd to an X window */
50 XContext winContext = 0;
52 Atom wmProtocols = None;
53 Atom wmDeleteWindow = None;
54 Atom dndProtocol = None;
55 Atom dndSelection = None;
56 Atom wmChangeState = None;
58 Atom kwmDockWindow = None;
60 /***********************************************************************
61 * X11DRV_WND_GetXWindow
63 * Return the X window associated to a window.
65 Window X11DRV_WND_GetXWindow(WND *wndPtr)
67 return wndPtr && wndPtr->pDriverData ?
68 ((X11DRV_WND_DATA *) wndPtr->pDriverData)->window : 0;
71 /***********************************************************************
72 * X11DRV_WND_FindXWindow
74 * Return the the first X window associated to a window chain.
76 Window X11DRV_WND_FindXWindow(WND *wndPtr)
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;
85 /***********************************************************************
86 * X11DRV_WND_RegisterWindow
88 * Associate an X window to a HWND.
90 static void X11DRV_WND_RegisterWindow(WND *wndPtr)
92 TSXSetWMProtocols( display, X11DRV_WND_GetXWindow(wndPtr), &wmDeleteWindow, 1 );
94 if (!winContext) winContext = TSXUniqueContext();
95 TSXSaveContext( display, X11DRV_WND_GetXWindow(wndPtr),
96 winContext, (char *) wndPtr->hwndSelf );
99 /***********************************************************************
100 * X11DRV_WND_IsZeroSizeWnd
102 * Return TRUE if the window has a height or widht less or equal to 0
104 static BOOL X11DRV_WND_IsZeroSizeWnd(WND *wndPtr)
106 if ( (wndPtr->rectWindow.left >= wndPtr->rectWindow.right) ||
107 (wndPtr->rectWindow.top >= wndPtr->rectWindow.bottom) )
108 return TRUE;
109 else
110 return FALSE;
113 /**********************************************************************
114 * X11DRV_WND_Initialize
116 void X11DRV_WND_Initialize(WND *wndPtr)
118 X11DRV_WND_DATA *pWndDriverData =
119 (X11DRV_WND_DATA *) HeapAlloc(SystemHeap, 0, sizeof(X11DRV_WND_DATA));
121 wndPtr->pDriverData = (void *) pWndDriverData;
123 pWndDriverData->window = 0;
126 /**********************************************************************
127 * X11DRV_WND_Finalize
129 void X11DRV_WND_Finalize(WND *wndPtr)
131 X11DRV_WND_DATA *pWndDriverData =
132 (X11DRV_WND_DATA *) wndPtr->pDriverData;
134 if (!wndPtr->pDriverData) {
135 ERR("Trying to destroy window again. Not good.\n");
136 return;
138 if(pWndDriverData->window)
140 ERR(
141 "WND destroyed without destroying "
142 "the associated X Window (%ld)\n",
143 pWndDriverData->window
146 HeapFree(SystemHeap, 0, wndPtr->pDriverData);
147 wndPtr->pDriverData = NULL;
150 /**********************************************************************
151 * X11DRV_WND_CreateDesktopWindow
153 BOOL X11DRV_WND_CreateDesktopWindow(WND *wndPtr, CLASS *classPtr, BOOL bUnicode)
155 if (wmProtocols == None)
156 wmProtocols = TSXInternAtom( display, "WM_PROTOCOLS", True );
157 if (wmDeleteWindow == None)
158 wmDeleteWindow = TSXInternAtom( display, "WM_DELETE_WINDOW", True );
159 if( dndProtocol == None )
160 dndProtocol = TSXInternAtom( display, "DndProtocol" , False );
161 if( dndSelection == None )
162 dndSelection = TSXInternAtom( display, "DndSelection" , False );
163 if( wmChangeState == None )
164 wmChangeState = TSXInternAtom (display, "WM_CHANGE_STATE", False);
165 if (kwmDockWindow == None)
166 kwmDockWindow = TSXInternAtom( display, "KWM_DOCKWINDOW", False );
168 ((X11DRV_WND_DATA *) wndPtr->pDriverData)->window = X11DRV_GetXRootWindow();
169 X11DRV_WND_RegisterWindow( wndPtr );
171 return TRUE;
174 /**********************************************************************
175 * X11DRV_WND_IconChanged
177 * hIcon or hIconSm has changed (or is being initialised for the
178 * first time). Complete the X11 driver-specific initialisation.
180 * This is not entirely correct, may need to create
181 * an icon window and set the pixmap as a background
183 static void X11DRV_WND_IconChanged(WND *wndPtr)
186 HICON16 hIcon = NC_IconForWindow(wndPtr);
188 if( ((X11DRV_WND_DATA *) wndPtr->pDriverData)->hWMIconBitmap )
189 DeleteObject( ((X11DRV_WND_DATA *) wndPtr->pDriverData)->hWMIconBitmap );
191 if( ((X11DRV_WND_DATA *) wndPtr->pDriverData)->hWMIconMask )
192 DeleteObject( ((X11DRV_WND_DATA *) wndPtr->pDriverData)->hWMIconMask);
194 if (!hIcon)
196 ((X11DRV_WND_DATA *) wndPtr->pDriverData)->hWMIconBitmap= 0;
197 ((X11DRV_WND_DATA *) wndPtr->pDriverData)->hWMIconMask= 0;
199 else
201 HBITMAP hbmOrig;
202 RECT rcMask;
203 BITMAP bmMask;
204 ICONINFO ii;
205 HDC hDC;
207 GetIconInfo(hIcon, &ii);
209 X11DRV_CreateBitmap(ii.hbmMask);
210 X11DRV_CreateBitmap(ii.hbmColor);
212 GetObjectA(ii.hbmMask, sizeof(bmMask), &bmMask);
213 rcMask.top = 0;
214 rcMask.left = 0;
215 rcMask.right = bmMask.bmWidth;
216 rcMask.bottom = bmMask.bmHeight;
218 hDC = CreateCompatibleDC(0);
219 hbmOrig = SelectObject(hDC, ii.hbmMask);
220 InvertRect(hDC, &rcMask);
221 SelectObject(hDC, hbmOrig);
222 DeleteDC(hDC);
224 ((X11DRV_WND_DATA *) wndPtr->pDriverData)->hWMIconBitmap = ii.hbmColor;
225 ((X11DRV_WND_DATA *) wndPtr->pDriverData)->hWMIconMask= ii.hbmMask;
227 return;
230 static void X11DRV_WND_SetIconHints(WND *wndPtr, XWMHints *hints)
232 if (((X11DRV_WND_DATA *) wndPtr->pDriverData)->hWMIconBitmap)
234 hints->icon_pixmap
235 = X11DRV_BITMAP_Pixmap(((X11DRV_WND_DATA *) wndPtr->pDriverData)->hWMIconBitmap);
236 hints->flags |= IconPixmapHint;
238 else
239 hints->flags &= ~IconPixmapHint;
241 if (((X11DRV_WND_DATA *) wndPtr->pDriverData)->hWMIconMask)
243 hints->icon_mask
244 = X11DRV_BITMAP_Pixmap(((X11DRV_WND_DATA *) wndPtr->pDriverData)->hWMIconMask);
245 hints->flags |= IconMaskHint;
247 else
248 hints->flags &= ~IconMaskHint;
251 /**********************************************************************
252 * X11DRV_WND_UpdateIconHints
254 * hIcon or hIconSm has changed (or is being initialised for the
255 * first time). Complete the X11 driver-specific initialisation
256 * and set the window hints.
258 * This is not entirely correct, may need to create
259 * an icon window and set the pixmap as a background
261 static void X11DRV_WND_UpdateIconHints(WND *wndPtr)
263 XWMHints* wm_hints;
265 X11DRV_WND_IconChanged(wndPtr);
267 wm_hints = TSXGetWMHints( display, X11DRV_WND_GetXWindow(wndPtr) );
268 if (!wm_hints) wm_hints = TSXAllocWMHints();
269 if (wm_hints)
271 X11DRV_WND_SetIconHints(wndPtr, wm_hints);
272 TSXSetWMHints( display, X11DRV_WND_GetXWindow(wndPtr), wm_hints );
273 TSXFree( wm_hints );
278 /**********************************************************************
279 * X11DRV_WND_CreateWindow
281 BOOL X11DRV_WND_CreateWindow(WND *wndPtr, CLASS *classPtr, CREATESTRUCTA *cs, BOOL bUnicode)
283 /* Create the X window (only for top-level windows, and then only */
284 /* when there's no desktop window) */
286 if ((X11DRV_GetXRootWindow() == DefaultRootWindow(display))
287 && (wndPtr->parent->hwndSelf == GetDesktopWindow()))
289 Window wGroupLeader;
290 XWMHints* wm_hints;
291 XSetWindowAttributes win_attr;
293 /* Create "managed" windows only if a title bar or resizable */
294 /* frame is required. */
295 if (WIN_WindowNeedsWMBorder(cs->style, cs->dwExStyle)) {
296 win_attr.event_mask = ExposureMask | KeyPressMask |
297 KeyReleaseMask | PointerMotionMask |
298 ButtonPressMask | ButtonReleaseMask |
299 FocusChangeMask | StructureNotifyMask;
300 win_attr.override_redirect = FALSE;
301 wndPtr->flags |= WIN_MANAGED;
302 } else {
303 win_attr.event_mask = ExposureMask | KeyPressMask |
304 KeyReleaseMask | PointerMotionMask |
305 ButtonPressMask | ButtonReleaseMask |
306 FocusChangeMask;
307 win_attr.override_redirect = TRUE;
309 wndPtr->flags |= WIN_NATIVE;
311 win_attr.bit_gravity = (classPtr->style & (CS_VREDRAW | CS_HREDRAW)) ? BGForget : BGNorthWest;
312 win_attr.colormap = X11DRV_PALETTE_PaletteXColormap;
313 win_attr.backing_store = NotUseful;
314 win_attr.save_under = ((classPtr->style & CS_SAVEBITS) != 0);
315 win_attr.cursor = X11DRV_MOUSE_XCursor;
317 ((X11DRV_WND_DATA *) wndPtr->pDriverData)->hWMIconBitmap = 0;
318 ((X11DRV_WND_DATA *) wndPtr->pDriverData)->hWMIconMask = 0;
319 ((X11DRV_WND_DATA *) wndPtr->pDriverData)->bit_gravity = win_attr.bit_gravity;
321 /* Zero-size X11 window hack. X doesn't like them, and will crash */
322 /* with a BadValue unless we do something ugly like this. */
323 /* Zero size window won't be mapped */
324 if (cs->cx <= 0) cs->cx = 1;
325 if (cs->cy <= 0) cs->cy = 1;
328 ((X11DRV_WND_DATA *) wndPtr->pDriverData)->window =
329 TSXCreateWindow( display, X11DRV_GetXRootWindow(),
330 cs->x, cs->y, cs->cx, cs->cy,
331 0, CopyFromParent,
332 InputOutput, CopyFromParent,
333 CWEventMask | CWOverrideRedirect |
334 CWColormap | CWCursor | CWSaveUnder |
335 CWBackingStore | CWBitGravity,
336 &win_attr );
338 if(!(wGroupLeader = X11DRV_WND_GetXWindow(wndPtr)))
339 return FALSE;
341 /* If we are the systray, we need to be managed to be noticed by KWM */
343 if (wndPtr->dwExStyle & WS_EX_TRAYWINDOW)
344 X11DRV_WND_DockWindow(wndPtr);
346 if (wndPtr->flags & WIN_MANAGED)
348 XClassHint *class_hints = TSXAllocClassHint();
349 XSizeHints* size_hints = TSXAllocSizeHints();
351 if (class_hints)
353 class_hints->res_name = "wineManaged";
354 class_hints->res_class = "Wine";
355 TSXSetClassHint( display, ((X11DRV_WND_DATA *) wndPtr->pDriverData)->window, class_hints );
356 TSXFree (class_hints);
359 if (size_hints)
361 size_hints->win_gravity = StaticGravity;
362 size_hints->x = cs->x;
363 size_hints->y = cs->y;
364 size_hints->flags = PWinGravity|PPosition;
366 if (HAS_DLGFRAME(cs->style,cs->dwExStyle))
368 size_hints->min_width = size_hints->max_width = cs->cx;
369 size_hints->min_height = size_hints->max_height = cs->cy;
370 size_hints->flags |= PMinSize | PMaxSize;
373 TSXSetWMSizeHints( display, X11DRV_WND_GetXWindow(wndPtr),
374 size_hints, XA_WM_NORMAL_HINTS );
375 TSXFree(size_hints);
379 if (cs->hwndParent) /* Get window owner */
381 Window w;
382 WND *tmpWnd = WIN_FindWndPtr(cs->hwndParent);
384 w = X11DRV_WND_FindXWindow( tmpWnd );
385 if (w != None)
387 TSXSetTransientForHint( display, X11DRV_WND_GetXWindow(wndPtr), w );
388 wGroupLeader = w;
390 WIN_ReleaseWndPtr(tmpWnd);
393 if ((wm_hints = TSXAllocWMHints()))
395 wm_hints->flags = InputHint | StateHint | WindowGroupHint;
396 wm_hints->input = True;
398 if( wndPtr->flags & WIN_MANAGED )
400 X11DRV_WND_IconChanged(wndPtr);
401 X11DRV_WND_SetIconHints(wndPtr, wm_hints);
403 wm_hints->initial_state = (wndPtr->dwStyle & WS_MINIMIZE)
404 ? IconicState : NormalState;
406 else
407 wm_hints->initial_state = NormalState;
408 wm_hints->window_group = wGroupLeader;
410 TSXSetWMHints( display, X11DRV_WND_GetXWindow(wndPtr), wm_hints );
411 TSXFree(wm_hints);
413 X11DRV_WND_RegisterWindow( wndPtr );
415 return TRUE;
418 /***********************************************************************
419 * X11DRV_WND_DestroyWindow
421 BOOL X11DRV_WND_DestroyWindow(WND *wndPtr)
423 Window w;
424 if ((w = X11DRV_WND_GetXWindow(wndPtr)))
426 XEvent xe;
427 TSXDeleteContext( display, w, winContext );
428 TSXDestroyWindow( display, w );
429 while( TSXCheckWindowEvent(display, w, NoEventMask, &xe) );
431 ((X11DRV_WND_DATA *) wndPtr->pDriverData)->window = None;
432 if( ((X11DRV_WND_DATA *) wndPtr->pDriverData)->hWMIconBitmap )
434 DeleteObject( ((X11DRV_WND_DATA *) wndPtr->pDriverData)->hWMIconBitmap );
435 ((X11DRV_WND_DATA *) wndPtr->pDriverData)->hWMIconBitmap = 0;
437 if( ((X11DRV_WND_DATA *) wndPtr->pDriverData)->hWMIconMask )
439 DeleteObject( ((X11DRV_WND_DATA *) wndPtr->pDriverData)->hWMIconMask);
440 ((X11DRV_WND_DATA *) wndPtr->pDriverData)->hWMIconMask= 0;
444 return TRUE;
447 /*****************************************************************
448 * X11DRV_WND_SetParent
450 WND *X11DRV_WND_SetParent(WND *wndPtr, WND *pWndParent)
452 WND *pDesktop = WIN_GetDesktop();
454 if( wndPtr && pWndParent && (wndPtr != pDesktop) )
456 WND* pWndPrev = wndPtr->parent;
458 if( pWndParent != pWndPrev )
460 if ( X11DRV_WND_GetXWindow(wndPtr) )
462 /* Toplevel window needs to be reparented. Used by Tk 8.0 */
464 TSXDestroyWindow( display, X11DRV_WND_GetXWindow(wndPtr) );
465 ((X11DRV_WND_DATA *) wndPtr->pDriverData)->window = None;
468 WIN_UnlinkWindow(wndPtr->hwndSelf);
469 wndPtr->parent = pWndParent;
471 /* Create an X counterpart for reparented top-level windows
472 * when not in the desktop mode. */
474 if( pWndParent == pDesktop )
476 if( X11DRV_GetXRootWindow() == DefaultRootWindow(display) )
478 CREATESTRUCTA cs;
479 cs.lpCreateParams = NULL;
480 cs.hInstance = 0; /* not used in following call */
481 cs.hMenu = 0; /* not used in following call */
482 cs.hwndParent = pWndParent->hwndSelf;
483 cs.cy = wndPtr->rectWindow.bottom - wndPtr->rectWindow.top;
484 if (!cs.cy)
485 cs.cy = 1;
486 cs.cx = wndPtr->rectWindow.right - wndPtr->rectWindow.left;
487 if (!cs.cx)
488 cs.cx = 1;
489 cs.y = wndPtr->rectWindow.top;
490 cs.x = wndPtr->rectWindow.left;
491 cs.style = wndPtr->dwStyle;
492 cs.lpszName = 0; /* not used in following call */
493 cs.lpszClass = 0; /*not used in following call */
494 cs.dwExStyle = wndPtr->dwExStyle;
495 X11DRV_WND_CreateWindow(wndPtr, wndPtr->class,
496 &cs, FALSE);
499 else /* a child window */
501 if( !( wndPtr->dwStyle & WS_CHILD ) )
503 if( wndPtr->wIDmenu != 0)
505 DestroyMenu( (HMENU) wndPtr->wIDmenu );
506 wndPtr->wIDmenu = 0;
510 WIN_LinkWindow(wndPtr->hwndSelf, HWND_TOP);
512 WIN_ReleaseDesktop();
513 return pWndPrev;
514 } /* failure */
515 WIN_ReleaseDesktop();
516 return 0;
519 /***********************************************************************
520 * X11DRV_WND_ForceWindowRaise
522 * Raise a window on top of the X stacking order, while preserving
523 * the correct Windows Z order.
525 void X11DRV_WND_ForceWindowRaise(WND *wndPtr)
527 XWindowChanges winChanges;
528 WND *wndPrev,*pDesktop = WIN_GetDesktop();
530 if (X11DRV_WND_IsZeroSizeWnd(wndPtr))
532 WIN_ReleaseDesktop();
533 return;
536 if( !wndPtr || !X11DRV_WND_GetXWindow(wndPtr) || (wndPtr->flags & WIN_MANAGED) )
538 WIN_ReleaseDesktop();
539 return;
542 /* Raise all windows up to wndPtr according to their Z order.
543 * (it would be easier with sibling-related Below but it doesn't
544 * work very well with SGI mwm for instance)
546 winChanges.stack_mode = Above;
547 while (wndPtr)
549 if ( !X11DRV_WND_IsZeroSizeWnd(wndPtr) && X11DRV_WND_GetXWindow(wndPtr) )
550 TSXReconfigureWMWindow( display, X11DRV_WND_GetXWindow(wndPtr), 0,
551 CWStackMode, &winChanges );
553 wndPrev = pDesktop->child;
554 if (wndPrev == wndPtr) break;
555 while (wndPrev && (wndPrev->next != wndPtr)) wndPrev = wndPrev->next;
557 wndPtr = wndPrev;
559 WIN_ReleaseDesktop();
562 /***********************************************************************
563 * X11DRV_WND_FindDesktopXWindow [Internal]
565 * Find the actual X window which needs be restacked.
566 * Used by X11DRV_WND_SetWindowPos().
568 static Window X11DRV_WND_FindDesktopXWindow( WND *wndPtr )
570 if (!(wndPtr->flags & WIN_MANAGED))
571 return X11DRV_WND_GetXWindow(wndPtr);
572 else
574 Window window, root, parent, *children;
575 int nchildren;
576 window = X11DRV_WND_GetXWindow(wndPtr);
577 for (;;)
579 TSXQueryTree( display, window, &root, &parent,
580 &children, &nchildren );
581 TSXFree( children );
582 if (parent == root)
583 return window;
584 window = parent;
589 /***********************************************************************
590 * WINPOS_SetXWindowPos
592 * SetWindowPos() for an X window. Used by the real SetWindowPos().
594 void X11DRV_WND_SetWindowPos(WND *wndPtr, const WINDOWPOS *winpos, BOOL bChangePos)
596 XWindowChanges winChanges;
597 int changeMask = 0;
598 BOOL isZeroSizeWnd = FALSE;
599 BOOL forceMapWindow = FALSE;
600 WND *winposPtr = WIN_FindWndPtr( winpos->hwnd );
601 if ( !winposPtr ) return;
603 /* find out if after this function we will end out with a zero-size window */
604 if (X11DRV_WND_IsZeroSizeWnd(winposPtr))
606 /* if current size is 0, and no resizing */
607 if (winpos->flags & SWP_NOSIZE)
608 isZeroSizeWnd = TRUE;
609 else if ((winpos->cx > 0) && (winpos->cy > 0))
611 /* if this function is setting a new size > 0 for the window, we
612 should map the window if WS_VISIBLE is set */
613 if ((winposPtr->dwStyle & WS_VISIBLE) && !(winpos->flags & SWP_HIDEWINDOW))
614 forceMapWindow = TRUE;
617 /* if resizing to 0 */
618 if ( !(winpos->flags & SWP_NOSIZE) && ((winpos->cx <= 0) || (winpos->cy <= 0)) )
619 isZeroSizeWnd = TRUE;
621 if(!wndPtr->hwndSelf) wndPtr = NULL; /* FIXME: WND destroyed, shouldn't happen!!! */
623 if (!(winpos->flags & SWP_SHOWWINDOW) && (winpos->flags & SWP_HIDEWINDOW))
625 if(X11DRV_WND_GetXWindow(wndPtr))
626 TSXUnmapWindow( display, X11DRV_WND_GetXWindow(wndPtr) );
629 if(bChangePos)
631 if ( !(winpos->flags & SWP_NOSIZE))
633 winChanges.width = (winpos->cx > 0 ) ? winpos->cx : 1;
634 winChanges.height = (winpos->cy > 0 ) ? winpos->cy : 1;
635 changeMask |= CWWidth | CWHeight;
637 /* Tweak dialog window size hints */
639 if ((winposPtr->flags & WIN_MANAGED) &&
640 HAS_DLGFRAME(winposPtr->dwStyle,winposPtr->dwExStyle))
642 XSizeHints *size_hints = TSXAllocSizeHints();
644 if (size_hints)
646 long supplied_return;
648 TSXGetWMSizeHints( display, X11DRV_WND_GetXWindow(winposPtr), size_hints,
649 &supplied_return, XA_WM_NORMAL_HINTS);
650 size_hints->min_width = size_hints->max_width = winpos->cx;
651 size_hints->min_height = size_hints->max_height = winpos->cy;
652 TSXSetWMSizeHints( display, X11DRV_WND_GetXWindow(winposPtr), size_hints,
653 XA_WM_NORMAL_HINTS );
654 TSXFree(size_hints);
658 if (!(winpos->flags & SWP_NOMOVE))
660 winChanges.x = winpos->x;
661 winChanges.y = winpos->y;
662 changeMask |= CWX | CWY;
664 if (!(winpos->flags & SWP_NOZORDER) && !isZeroSizeWnd)
666 winChanges.stack_mode = Below;
667 changeMask |= CWStackMode;
669 if (winpos->hwndInsertAfter == HWND_TOP) winChanges.stack_mode = Above;
670 else if (winpos->hwndInsertAfter != HWND_BOTTOM)
672 WND* insertPtr = WIN_FindWndPtr( winpos->hwndInsertAfter );
673 Window stack[2];
675 stack[0] = X11DRV_WND_FindDesktopXWindow( insertPtr );
676 stack[1] = X11DRV_WND_FindDesktopXWindow( winposPtr );
678 /* for stupid window managers (i.e. all of them) */
680 if (!X11DRV_WND_IsZeroSizeWnd(insertPtr))
682 TSXRestackWindows(display, stack, 2);
683 changeMask &= ~CWStackMode;
685 WIN_ReleaseWndPtr(insertPtr);
688 if (changeMask && X11DRV_WND_GetXWindow(winposPtr))
690 TSXReconfigureWMWindow( display, X11DRV_WND_GetXWindow(winposPtr), 0, changeMask, &winChanges );
691 if( winposPtr->class->style & (CS_VREDRAW | CS_HREDRAW) )
692 X11DRV_WND_SetHostAttr( winposPtr, HAK_BITGRAVITY, BGForget );
696 /* don't map the window if it's a zero size window */
697 if ( ((winpos->flags & SWP_SHOWWINDOW) && !isZeroSizeWnd) || forceMapWindow )
699 if(X11DRV_WND_GetXWindow(wndPtr))
700 TSXMapWindow( display, X11DRV_WND_GetXWindow(wndPtr) );
702 WIN_ReleaseWndPtr(winposPtr);
705 /*****************************************************************
706 * X11DRV_WND_SetText
708 void X11DRV_WND_SetText(WND *wndPtr, LPCWSTR text)
710 UINT count;
711 char *buffer;
712 static UINT text_cp = (UINT)-1;
713 Window win;
715 if (!(win = X11DRV_WND_GetXWindow(wndPtr))) return;
717 if(text_cp == (UINT)-1)
719 text_cp = PROFILE_GetWineIniInt("x11drv", "TextCP", CP_ACP);
720 TRACE("text_cp = %u\n", text_cp);
723 /* allocate new buffer for window text */
724 count = WideCharToMultiByte(text_cp, 0, text, -1, NULL, 0, NULL, NULL);
725 if (!(buffer = HeapAlloc( GetProcessHeap(), 0, count * sizeof(WCHAR) )))
727 ERR("Not enough memory for window text\n");
728 return;
730 WideCharToMultiByte(text_cp, 0, text, -1, buffer, count, NULL, NULL);
732 TSXStoreName( display, win, buffer );
733 TSXSetIconName( display, win, buffer );
734 HeapFree( GetProcessHeap(), 0, buffer );
737 /*****************************************************************
738 * X11DRV_WND_SetFocus
740 * Set the X focus.
741 * Explicit colormap management seems to work only with OLVWM.
743 void X11DRV_WND_SetFocus(WND *wndPtr)
745 HWND hwnd = wndPtr->hwndSelf;
746 XWindowAttributes win_attr;
747 Window win;
748 WND *w = wndPtr;
750 if (X11DRV_WND_IsZeroSizeWnd(wndPtr))
751 return;
753 /* Only mess with the X focus if there's */
754 /* no desktop window and if the window is not managed by the WM. */
755 if ((X11DRV_GetXRootWindow() != DefaultRootWindow(display))) return;
756 while (w && !((X11DRV_WND_DATA *) w->pDriverData)->window)
757 w = w->parent;
758 if (!w) w = wndPtr;
759 if (w->flags & WIN_MANAGED) return;
761 if (!hwnd) /* If setting the focus to 0, uninstall the colormap */
763 if (X11DRV_PALETTE_PaletteFlags & X11DRV_PALETTE_PRIVATE)
764 TSXUninstallColormap( display, X11DRV_PALETTE_PaletteXColormap );
765 return;
768 /* Set X focus and install colormap */
770 if (!(win = X11DRV_WND_FindXWindow(wndPtr))) return;
771 if (!TSXGetWindowAttributes( display, win, &win_attr ) ||
772 (win_attr.map_state != IsViewable))
773 return; /* If window is not viewable, don't change anything */
775 TSXSetInputFocus( display, win, RevertToParent, CurrentTime );
776 if (X11DRV_PALETTE_PaletteFlags & X11DRV_PALETTE_PRIVATE)
777 TSXInstallColormap( display, X11DRV_PALETTE_PaletteXColormap );
779 EVENT_Synchronize();
782 /*****************************************************************
783 * X11DRV_WND_PreSizeMove
785 void X11DRV_WND_PreSizeMove(WND *wndPtr)
787 if (!(wndPtr->dwStyle & WS_CHILD) && (X11DRV_GetXRootWindow() == DefaultRootWindow(display)))
788 TSXGrabServer( display );
791 /*****************************************************************
792 * X11DRV_WND_PostSizeMove
794 void X11DRV_WND_PostSizeMove(WND *wndPtr)
796 if (!(wndPtr->dwStyle & WS_CHILD) &&
797 (X11DRV_GetXRootWindow() == DefaultRootWindow(display)))
798 TSXUngrabServer( display );
801 /*****************************************************************
802 * X11DRV_WND_SurfaceCopy
804 * Copies rect to (rect.left + dx, rect.top + dy).
806 void X11DRV_WND_SurfaceCopy(WND* wndPtr, HDC hdc, INT dx, INT dy,
807 const RECT *rect, BOOL bUpdate)
809 X11DRV_PDEVICE *physDev;
810 POINT dst, src;
811 DC *dcPtr = DC_GetDCPtr( hdc );
813 if (!dcPtr) return;
814 physDev = (X11DRV_PDEVICE *)dcPtr->physDev;
815 dst.x = (src.x = dcPtr->w.DCOrgX + rect->left) + dx;
816 dst.y = (src.y = dcPtr->w.DCOrgY + rect->top) + dy;
818 if (bUpdate) /* handles non-Wine windows hanging over the copied area */
819 TSXSetGraphicsExposures( display, physDev->gc, True );
820 TSXSetFunction( display, physDev->gc, GXcopy );
821 TSXCopyArea( display, physDev->drawable, physDev->drawable,
822 physDev->gc, src.x, src.y,
823 rect->right - rect->left,
824 rect->bottom - rect->top,
825 dst.x, dst.y );
826 if (bUpdate)
827 TSXSetGraphicsExposures( display, physDev->gc, False );
829 if (bUpdate) /* Make sure exposure events have been processed */
830 EVENT_Synchronize();
831 GDI_HEAP_UNLOCK( hdc );
834 /***********************************************************************
835 * X11DRV_WND_SetDrawable
837 * Set the drawable, origin and dimensions for the DC associated to
838 * a given window.
840 void X11DRV_WND_SetDrawable(WND *wndPtr, HDC hdc, WORD flags, BOOL bSetClipOrigin)
842 DC *dc = DC_GetDCPtr( hdc );
843 X11DRV_PDEVICE *physDev;
844 INT dcOrgXCopy = 0, dcOrgYCopy = 0;
845 BOOL offsetClipRgn = FALSE;
847 if (!dc) return;
848 physDev = (X11DRV_PDEVICE *)dc->physDev;
849 if (!wndPtr) /* Get a DC for the whole screen */
851 dc->w.DCOrgX = 0;
852 dc->w.DCOrgY = 0;
853 physDev->drawable = X11DRV_GetXRootWindow();
854 TSXSetSubwindowMode( display, physDev->gc, IncludeInferiors );
856 else
859 * This function change the coordinate system (DCOrgX,DCOrgY)
860 * values. When it moves the origin, other data like the current clipping
861 * region will not be moved to that new origin. In the case of DCs that are class
862 * or window DCs that clipping region might be a valid value from a previous use
863 * of the DC and changing the origin of the DC without moving the clip region
864 * results in a clip region that is not placed properly in the DC.
865 * This code will save the dc origin, let the SetDrawable
866 * modify the origin and reset the clipping. When the clipping is set,
867 * it is moved according to the new DC origin.
869 if ( (wndPtr->class->style & (CS_OWNDC | CS_CLASSDC)) && (dc->w.hClipRgn > 0))
871 dcOrgXCopy = dc->w.DCOrgX;
872 dcOrgYCopy = dc->w.DCOrgY;
873 offsetClipRgn = TRUE;
876 if (flags & DCX_WINDOW)
878 dc->w.DCOrgX = wndPtr->rectWindow.left;
879 dc->w.DCOrgY = wndPtr->rectWindow.top;
881 else
883 dc->w.DCOrgX = wndPtr->rectClient.left;
884 dc->w.DCOrgY = wndPtr->rectClient.top;
886 while (!X11DRV_WND_GetXWindow(wndPtr))
888 wndPtr = wndPtr->parent;
889 dc->w.DCOrgX += wndPtr->rectClient.left;
890 dc->w.DCOrgY += wndPtr->rectClient.top;
892 dc->w.DCOrgX -= wndPtr->rectWindow.left;
893 dc->w.DCOrgY -= wndPtr->rectWindow.top;
895 /* reset the clip region, according to the new origin */
896 if ( offsetClipRgn )
898 OffsetRgn(dc->w.hClipRgn, dc->w.DCOrgX - dcOrgXCopy,dc->w.DCOrgY - dcOrgYCopy);
901 physDev->drawable = X11DRV_WND_GetXWindow(wndPtr);
903 #if 0
904 /* This is needed when we reuse a cached DC because
905 * SetDCState() called by ReleaseDC() screws up DC
906 * origins for child windows.
909 if( bSetClipOrigin )
910 TSXSetClipOrigin( display, physDev->gc, dc->w.DCOrgX, dc->w.DCOrgY );
911 #endif
913 GDI_HEAP_UNLOCK( hdc );
916 /***********************************************************************
917 * X11DRV_SetWMHint
919 static BOOL X11DRV_SetWMHint(Display* display, WND* wndPtr, int hint, int val)
921 XWMHints* wm_hints = TSXGetWMHints( display, X11DRV_WND_GetXWindow(wndPtr) );
922 if (!wm_hints) wm_hints = TSXAllocWMHints();
923 if (wm_hints)
925 wm_hints->flags = hint;
926 switch( hint )
928 case InputHint:
929 wm_hints->input = val;
930 break;
932 case StateHint:
933 wm_hints->initial_state = val;
934 break;
936 case IconPixmapHint:
937 wm_hints->icon_pixmap = (Pixmap)val;
938 break;
940 case IconWindowHint:
941 wm_hints->icon_window = (Window)val;
942 break;
945 TSXSetWMHints( display, X11DRV_WND_GetXWindow(wndPtr), wm_hints );
946 TSXFree(wm_hints);
947 return TRUE;
949 return FALSE;
953 /***********************************************************************
954 * X11DRV_WND_SetHostAttr
956 * This function returns TRUE if the attribute is supported and the
957 * action was successful. Otherwise it should return FALSE and Wine will try
958 * to get by without the functionality provided by the host window system.
960 BOOL X11DRV_WND_SetHostAttr(WND* wnd, INT ha, INT value)
962 Window w;
964 if( (w = X11DRV_WND_GetXWindow(wnd)) )
966 XSetWindowAttributes win_attr;
968 switch( ha )
970 case HAK_ICONICSTATE: /* called when a window is minimized/restored */
972 /* don't do anything if it'a zero size window */
973 if (X11DRV_WND_IsZeroSizeWnd(wnd))
974 return TRUE;
976 if( (wnd->flags & WIN_MANAGED) )
978 if( value )
980 if( wnd->dwStyle & WS_VISIBLE )
982 XClientMessageEvent ev;
984 /* FIXME: set proper icon */
986 ev.type = ClientMessage;
987 ev.display = display;
988 ev.message_type = wmChangeState;
989 ev.format = 32;
990 ev.data.l[0] = IconicState;
991 ev.window = w;
993 if( TSXSendEvent (display,
994 RootWindow( display, XScreenNumberOfScreen(X11DRV_GetXScreen()) ),
995 True, (SubstructureRedirectMask | SubstructureNotifyMask), (XEvent*)&ev))
997 XEvent xe;
998 TSXFlush (display);
999 while( !TSXCheckTypedWindowEvent( display, w, UnmapNotify, &xe) );
1001 else
1002 break;
1004 else
1005 X11DRV_SetWMHint( display, wnd, StateHint, IconicState );
1007 else
1009 if( !(wnd->flags & WS_VISIBLE) )
1010 X11DRV_SetWMHint( display, wnd, StateHint, NormalState );
1011 else
1013 XEvent xe;
1014 TSXMapWindow(display, w );
1015 while( !TSXCheckTypedWindowEvent( display, w, MapNotify, &xe) );
1018 return TRUE;
1020 break;
1022 case HAK_BITGRAVITY: /* called when a window is resized */
1024 if( ((X11DRV_WND_DATA *) wnd->pDriverData)->bit_gravity != value )
1026 win_attr.bit_gravity = value;
1027 ((X11DRV_WND_DATA *) wnd->pDriverData)->bit_gravity = value;
1028 TSXChangeWindowAttributes( display, w, CWBitGravity, &win_attr );
1030 return TRUE;
1032 case HAK_ICONS: /* called when the icons change */
1033 if ( (wnd->flags & WIN_MANAGED) )
1034 X11DRV_WND_UpdateIconHints(wnd);
1035 return TRUE;
1037 case HAK_ACCEPTFOCUS: /* called when a window is disabled/enabled */
1039 if( (wnd->flags & WIN_MANAGED) )
1040 return X11DRV_SetWMHint( display, wnd, InputHint, value );
1043 return FALSE;
1046 /***********************************************************************
1047 * X11DRV_WND_IsSelfClipping
1049 BOOL X11DRV_WND_IsSelfClipping(WND *wndPtr)
1051 return X11DRV_WND_GetXWindow(wndPtr) != None;
1054 /***********************************************************************
1055 * X11DRV_WND_DockWindow
1057 * Set the X Property of the window that tells the windowmanager we really
1058 * want to be in the systray
1060 * KDE: set "KWM_DOCKWINDOW", type "KWM_DOCKWINDOW" to 1 before a window is
1061 * mapped.
1063 * all others: to be added ;)
1065 void X11DRV_WND_DockWindow(WND *wndPtr)
1067 int data = 1;
1068 Window win = X11DRV_WND_GetXWindow(wndPtr);
1069 if (kwmDockWindow == None)
1070 return; /* no KDE running */
1071 TSXChangeProperty(
1072 display,win,kwmDockWindow,kwmDockWindow,32,PropModeReplace,(char*)&data,1
1077 /***********************************************************************
1078 * X11DRV_WND_SetWindowRgn
1080 * Assign specified region to window (for non-rectangular windows)
1082 void X11DRV_WND_SetWindowRgn(WND *wndPtr, HRGN hrgnWnd)
1084 #ifdef HAVE_LIBXSHAPE
1085 Window win = X11DRV_WND_GetXWindow(wndPtr);
1087 if (!win) return;
1089 if (!hrgnWnd)
1091 TSXShapeCombineMask( display, win, ShapeBounding, 0, 0, None, ShapeSet );
1093 else
1095 XRectangle *aXRect;
1096 DWORD size;
1097 DWORD dwBufferSize = GetRegionData(hrgnWnd, 0, NULL);
1098 PRGNDATA pRegionData = HeapAlloc(GetProcessHeap(), 0, dwBufferSize);
1099 if (!pRegionData) return;
1101 GetRegionData(hrgnWnd, dwBufferSize, pRegionData);
1102 size = pRegionData->rdh.nCount;
1103 /* convert region's "Windows rectangles" to XRectangles */
1104 aXRect = HeapAlloc(GetProcessHeap(), 0, size * sizeof(*aXRect) );
1105 if (aXRect)
1107 XRectangle* pCurrRect = aXRect;
1108 RECT *pRect = (RECT*) pRegionData->Buffer;
1109 for (; pRect < ((RECT*) pRegionData->Buffer) + size ; ++pRect, ++pCurrRect)
1111 pCurrRect->x = pRect->left;
1112 pCurrRect->y = pRect->top;
1113 pCurrRect->height = pRect->bottom - pRect->top;
1114 pCurrRect->width = pRect->right - pRect->left;
1116 TRACE("Rectangle %04d of %04ld data: X=%04d, Y=%04d, Height=%04d, Width=%04d.\n",
1117 pRect - (RECT*) pRegionData->Buffer,
1118 size,
1119 pCurrRect->x,
1120 pCurrRect->y,
1121 pCurrRect->height,
1122 pCurrRect->width);
1125 /* shape = non-rectangular windows (X11/extensions) */
1126 TSXShapeCombineRectangles( display, win, ShapeBounding,
1127 0, 0, aXRect,
1128 pCurrRect - aXRect, ShapeSet, YXBanded );
1129 HeapFree(GetProcessHeap(), 0, aXRect );
1131 HeapFree(GetProcessHeap(), 0, pRegionData);
1133 #endif /* HAVE_LIBXSHAPE */