Use the standard CreateThread routine to create 16-bit tasks instead
[wine.git] / windows / x11drv / wnd.c
blobfbed353cc1da8da3f386cc59c9675900bb89141d
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 "gdi.h"
23 #include "options.h"
24 #include "message.h"
25 #include "win.h"
26 #include "windef.h"
27 #include "x11drv.h"
28 #include "wingdi.h"
29 #include "winnls.h"
30 #include "wine/winuser16.h"
32 DEFAULT_DEBUG_CHANNEL(win);
34 /* Some useful macros */
35 #define HAS_DLGFRAME(style,exStyle) \
36 ((!((style) & WS_THICKFRAME)) && (((style) & WS_DLGFRAME) || ((exStyle) & WS_EX_DLGMODALFRAME)))
38 /**********************************************************************/
40 extern Cursor X11DRV_MOUSE_XCursor; /* Current X cursor */
41 extern BOOL X11DRV_CreateBitmap( HBITMAP );
42 extern Pixmap X11DRV_BITMAP_Pixmap( HBITMAP );
44 /**********************************************************************/
46 WND_DRIVER X11DRV_WND_Driver =
48 X11DRV_WND_Initialize,
49 X11DRV_WND_Finalize,
50 X11DRV_WND_CreateDesktopWindow,
51 X11DRV_WND_CreateWindow,
52 X11DRV_WND_DestroyWindow,
53 X11DRV_WND_SetParent,
54 X11DRV_WND_ForceWindowRaise,
55 X11DRV_WND_SetWindowPos,
56 X11DRV_WND_SetText,
57 X11DRV_WND_SetFocus,
58 X11DRV_WND_PreSizeMove,
59 X11DRV_WND_PostSizeMove,
60 X11DRV_WND_SurfaceCopy,
61 X11DRV_WND_SetDrawable,
62 X11DRV_WND_SetHostAttr,
63 X11DRV_WND_IsSelfClipping,
64 X11DRV_WND_SetWindowRgn
68 /* X context to associate a hwnd to an X window */
69 XContext winContext = 0;
71 Atom wmProtocols = None;
72 Atom wmDeleteWindow = None;
73 Atom dndProtocol = None;
74 Atom dndSelection = None;
75 Atom wmChangeState = None;
77 Atom kwmDockWindow = None;
78 Atom _net_kde_system_tray_window_for = None; /* KDE 2 Beta */
79 Atom _kde_net_wm_system_tray_window_for = None; /* KDE 2 Final */
81 /***********************************************************************
82 * X11DRV_WND_GetXWindow
84 * Return the X window associated to a window.
86 Window X11DRV_WND_GetXWindow(WND *wndPtr)
88 return wndPtr && wndPtr->pDriverData ?
89 ((X11DRV_WND_DATA *) wndPtr->pDriverData)->window : 0;
92 /***********************************************************************
93 * X11DRV_WND_FindXWindow
95 * Return the the first X window associated to a window chain.
97 Window X11DRV_WND_FindXWindow(WND *wndPtr)
99 while (wndPtr &&
100 !((X11DRV_WND_DATA *) wndPtr->pDriverData)->window)
101 wndPtr = wndPtr->parent;
102 return wndPtr ?
103 ((X11DRV_WND_DATA *) wndPtr->pDriverData)->window : 0;
106 /***********************************************************************
107 * X11DRV_WND_RegisterWindow
109 * Associate an X window to a HWND.
111 static void X11DRV_WND_RegisterWindow(WND *wndPtr)
113 TSXSetWMProtocols( display, X11DRV_WND_GetXWindow(wndPtr), &wmDeleteWindow, 1 );
115 if (!winContext) winContext = TSXUniqueContext();
116 TSXSaveContext( display, X11DRV_WND_GetXWindow(wndPtr),
117 winContext, (char *) wndPtr->hwndSelf );
120 /***********************************************************************
121 * X11DRV_WND_IsZeroSizeWnd
123 * Return TRUE if the window has a height or widht less or equal to 0
125 static BOOL X11DRV_WND_IsZeroSizeWnd(WND *wndPtr)
127 if ( (wndPtr->rectWindow.left >= wndPtr->rectWindow.right) ||
128 (wndPtr->rectWindow.top >= wndPtr->rectWindow.bottom) )
129 return TRUE;
130 else
131 return FALSE;
134 /**********************************************************************
135 * X11DRV_WND_Initialize
137 void X11DRV_WND_Initialize(WND *wndPtr)
139 X11DRV_WND_DATA *pWndDriverData = HeapAlloc(GetProcessHeap(), 0, sizeof(X11DRV_WND_DATA));
141 wndPtr->pDriverData = (void *) pWndDriverData;
143 pWndDriverData->window = 0;
146 /**********************************************************************
147 * X11DRV_WND_Finalize
149 void X11DRV_WND_Finalize(WND *wndPtr)
151 X11DRV_WND_DATA *pWndDriverData =
152 (X11DRV_WND_DATA *) wndPtr->pDriverData;
154 if (!wndPtr->pDriverData) {
155 ERR("Trying to destroy window again. Not good.\n");
156 return;
158 if(pWndDriverData->window)
160 ERR(
161 "WND destroyed without destroying "
162 "the associated X Window (%ld)\n",
163 pWndDriverData->window
166 HeapFree(GetProcessHeap(), 0, wndPtr->pDriverData);
167 wndPtr->pDriverData = NULL;
170 /**********************************************************************
171 * X11DRV_WND_CreateDesktopWindow
173 BOOL X11DRV_WND_CreateDesktopWindow(WND *wndPtr)
175 if (wmProtocols == None)
176 wmProtocols = TSXInternAtom( display, "WM_PROTOCOLS", True );
177 if (wmDeleteWindow == None)
178 wmDeleteWindow = TSXInternAtom( display, "WM_DELETE_WINDOW", True );
179 if( dndProtocol == None )
180 dndProtocol = TSXInternAtom( display, "DndProtocol" , False );
181 if( dndSelection == None )
182 dndSelection = TSXInternAtom( display, "DndSelection" , False );
183 if( wmChangeState == None )
184 wmChangeState = TSXInternAtom (display, "WM_CHANGE_STATE", False);
185 if (kwmDockWindow == None)
186 kwmDockWindow = TSXInternAtom( display, "KWM_DOCKWINDOW", False );
187 if (_kde_net_wm_system_tray_window_for == None)
188 _kde_net_wm_system_tray_window_for = TSXInternAtom( display, "_KDE_NET_WM_SYSTEM_TRAY_WINDOW_FOR", False );
189 if (_net_kde_system_tray_window_for == None)
190 _net_kde_system_tray_window_for = TSXInternAtom( display, "_NET_KDE_SYSTEM_TRAY_WINDOW_FOR", False );
192 ((X11DRV_WND_DATA *) wndPtr->pDriverData)->window = X11DRV_GetXRootWindow();
193 X11DRV_WND_RegisterWindow( wndPtr );
195 return TRUE;
198 /**********************************************************************
199 * X11DRV_WND_IconChanged
201 * hIcon or hIconSm has changed (or is being initialised for the
202 * first time). Complete the X11 driver-specific initialisation.
204 * This is not entirely correct, may need to create
205 * an icon window and set the pixmap as a background
207 static void X11DRV_WND_IconChanged(WND *wndPtr)
210 HICON16 hIcon = NC_IconForWindow(wndPtr);
212 if( ((X11DRV_WND_DATA *) wndPtr->pDriverData)->hWMIconBitmap )
213 DeleteObject( ((X11DRV_WND_DATA *) wndPtr->pDriverData)->hWMIconBitmap );
215 if( ((X11DRV_WND_DATA *) wndPtr->pDriverData)->hWMIconMask )
216 DeleteObject( ((X11DRV_WND_DATA *) wndPtr->pDriverData)->hWMIconMask);
218 if (!hIcon)
220 ((X11DRV_WND_DATA *) wndPtr->pDriverData)->hWMIconBitmap= 0;
221 ((X11DRV_WND_DATA *) wndPtr->pDriverData)->hWMIconMask= 0;
223 else
225 HBITMAP hbmOrig;
226 RECT rcMask;
227 BITMAP bmMask;
228 ICONINFO ii;
229 HDC hDC;
231 GetIconInfo(hIcon, &ii);
233 X11DRV_CreateBitmap(ii.hbmMask);
234 X11DRV_CreateBitmap(ii.hbmColor);
236 GetObjectA(ii.hbmMask, sizeof(bmMask), &bmMask);
237 rcMask.top = 0;
238 rcMask.left = 0;
239 rcMask.right = bmMask.bmWidth;
240 rcMask.bottom = bmMask.bmHeight;
242 hDC = CreateCompatibleDC(0);
243 hbmOrig = SelectObject(hDC, ii.hbmMask);
244 InvertRect(hDC, &rcMask);
245 SelectObject(hDC, hbmOrig);
246 DeleteDC(hDC);
248 ((X11DRV_WND_DATA *) wndPtr->pDriverData)->hWMIconBitmap = ii.hbmColor;
249 ((X11DRV_WND_DATA *) wndPtr->pDriverData)->hWMIconMask= ii.hbmMask;
251 return;
254 static void X11DRV_WND_SetIconHints(WND *wndPtr, XWMHints *hints)
256 if (((X11DRV_WND_DATA *) wndPtr->pDriverData)->hWMIconBitmap)
258 hints->icon_pixmap
259 = X11DRV_BITMAP_Pixmap(((X11DRV_WND_DATA *) wndPtr->pDriverData)->hWMIconBitmap);
260 hints->flags |= IconPixmapHint;
262 else
263 hints->flags &= ~IconPixmapHint;
265 if (((X11DRV_WND_DATA *) wndPtr->pDriverData)->hWMIconMask)
267 hints->icon_mask
268 = X11DRV_BITMAP_Pixmap(((X11DRV_WND_DATA *) wndPtr->pDriverData)->hWMIconMask);
269 hints->flags |= IconMaskHint;
271 else
272 hints->flags &= ~IconMaskHint;
275 /**********************************************************************
276 * X11DRV_WND_UpdateIconHints
278 * hIcon or hIconSm has changed (or is being initialised for the
279 * first time). Complete the X11 driver-specific initialisation
280 * and set the window hints.
282 * This is not entirely correct, may need to create
283 * an icon window and set the pixmap as a background
285 static void X11DRV_WND_UpdateIconHints(WND *wndPtr)
287 XWMHints* wm_hints;
289 X11DRV_WND_IconChanged(wndPtr);
291 wm_hints = TSXGetWMHints( display, X11DRV_WND_GetXWindow(wndPtr) );
292 if (!wm_hints) wm_hints = TSXAllocWMHints();
293 if (wm_hints)
295 X11DRV_WND_SetIconHints(wndPtr, wm_hints);
296 TSXSetWMHints( display, X11DRV_WND_GetXWindow(wndPtr), wm_hints );
297 TSXFree( wm_hints );
302 /**********************************************************************
303 * X11DRV_WND_CreateWindow
305 BOOL X11DRV_WND_CreateWindow(WND *wndPtr, CREATESTRUCTA *cs, BOOL bUnicode)
307 /* Create the X window (only for top-level windows, and then only */
308 /* when there's no desktop window) */
310 if ((X11DRV_GetXRootWindow() == DefaultRootWindow(display))
311 && (wndPtr->parent->hwndSelf == GetDesktopWindow()))
313 Window wGroupLeader;
314 XWMHints* wm_hints;
315 XSetWindowAttributes win_attr;
317 /* Create "managed" windows only if a title bar or resizable */
318 /* frame is required. */
319 if (WIN_WindowNeedsWMBorder(cs->style, cs->dwExStyle)) {
320 win_attr.event_mask = ExposureMask | KeyPressMask |
321 KeyReleaseMask | PointerMotionMask |
322 ButtonPressMask | ButtonReleaseMask |
323 FocusChangeMask | StructureNotifyMask;
324 win_attr.override_redirect = FALSE;
325 wndPtr->dwExStyle |= WS_EX_MANAGED;
326 } else {
327 win_attr.event_mask = ExposureMask | KeyPressMask |
328 KeyReleaseMask | PointerMotionMask |
329 ButtonPressMask | ButtonReleaseMask |
330 FocusChangeMask;
331 win_attr.override_redirect = TRUE;
333 wndPtr->flags |= WIN_NATIVE;
335 win_attr.bit_gravity = (wndPtr->clsStyle & (CS_VREDRAW | CS_HREDRAW)) ? BGForget : BGNorthWest;
336 win_attr.colormap = X11DRV_PALETTE_PaletteXColormap;
337 win_attr.backing_store = NotUseful;
338 win_attr.save_under = ((wndPtr->clsStyle & CS_SAVEBITS) != 0);
339 win_attr.cursor = X11DRV_MOUSE_XCursor;
341 ((X11DRV_WND_DATA *) wndPtr->pDriverData)->hWMIconBitmap = 0;
342 ((X11DRV_WND_DATA *) wndPtr->pDriverData)->hWMIconMask = 0;
343 ((X11DRV_WND_DATA *) wndPtr->pDriverData)->bit_gravity = win_attr.bit_gravity;
345 /* Zero-size X11 window hack. X doesn't like them, and will crash */
346 /* with a BadValue unless we do something ugly like this. */
347 /* Zero size window won't be mapped */
348 if (cs->cx <= 0) cs->cx = 1;
349 if (cs->cy <= 0) cs->cy = 1;
352 ((X11DRV_WND_DATA *) wndPtr->pDriverData)->window =
353 TSXCreateWindow( display, X11DRV_GetXRootWindow(),
354 cs->x, cs->y, cs->cx, cs->cy,
355 0, CopyFromParent,
356 InputOutput, CopyFromParent,
357 CWEventMask | CWOverrideRedirect |
358 CWColormap | CWCursor | CWSaveUnder |
359 CWBackingStore | CWBitGravity,
360 &win_attr );
362 if(!(wGroupLeader = X11DRV_WND_GetXWindow(wndPtr)))
363 return FALSE;
365 /* If we are the systray, we need to be managed to be noticed by KWM */
367 if (wndPtr->dwExStyle & WS_EX_TRAYWINDOW)
368 X11DRV_WND_DockWindow(wndPtr);
370 if (wndPtr->dwExStyle & WS_EX_MANAGED)
372 XClassHint *class_hints = TSXAllocClassHint();
373 XSizeHints* size_hints = TSXAllocSizeHints();
375 if (class_hints)
377 class_hints->res_name = "wineManaged";
378 class_hints->res_class = "Wine";
379 TSXSetClassHint( display, ((X11DRV_WND_DATA *) wndPtr->pDriverData)->window, class_hints );
380 TSXFree (class_hints);
383 if (size_hints)
385 size_hints->win_gravity = StaticGravity;
386 size_hints->x = cs->x;
387 size_hints->y = cs->y;
388 size_hints->flags = PWinGravity|PPosition;
390 if (HAS_DLGFRAME(cs->style,cs->dwExStyle))
392 size_hints->min_width = size_hints->max_width = cs->cx;
393 size_hints->min_height = size_hints->max_height = cs->cy;
394 size_hints->flags |= PMinSize | PMaxSize;
397 TSXSetWMSizeHints( display, X11DRV_WND_GetXWindow(wndPtr),
398 size_hints, XA_WM_NORMAL_HINTS );
399 TSXFree(size_hints);
403 if (cs->hwndParent) /* Get window owner */
405 Window w;
406 WND *tmpWnd = WIN_FindWndPtr(cs->hwndParent);
408 w = X11DRV_WND_FindXWindow( tmpWnd );
409 if (w != None)
411 TSXSetTransientForHint( display, X11DRV_WND_GetXWindow(wndPtr), w );
412 wGroupLeader = w;
414 WIN_ReleaseWndPtr(tmpWnd);
417 if ((wm_hints = TSXAllocWMHints()))
419 wm_hints->flags = InputHint | StateHint | WindowGroupHint;
420 wm_hints->input = True;
422 if (wndPtr->dwExStyle & WS_EX_MANAGED)
424 X11DRV_WND_IconChanged(wndPtr);
425 X11DRV_WND_SetIconHints(wndPtr, wm_hints);
427 wm_hints->initial_state = (wndPtr->dwStyle & WS_MINIMIZE)
428 ? IconicState : NormalState;
430 else
431 wm_hints->initial_state = NormalState;
432 wm_hints->window_group = wGroupLeader;
434 TSXSetWMHints( display, X11DRV_WND_GetXWindow(wndPtr), wm_hints );
435 TSXFree(wm_hints);
437 X11DRV_WND_RegisterWindow( wndPtr );
439 return TRUE;
442 /***********************************************************************
443 * X11DRV_WND_DestroyWindow
445 BOOL X11DRV_WND_DestroyWindow(WND *wndPtr)
447 Window w;
448 if ((w = X11DRV_WND_GetXWindow(wndPtr)))
450 XEvent xe;
451 TSXDeleteContext( display, w, winContext );
452 TSXDestroyWindow( display, w );
453 while( TSXCheckWindowEvent(display, w, NoEventMask, &xe) );
455 ((X11DRV_WND_DATA *) wndPtr->pDriverData)->window = None;
456 if( ((X11DRV_WND_DATA *) wndPtr->pDriverData)->hWMIconBitmap )
458 DeleteObject( ((X11DRV_WND_DATA *) wndPtr->pDriverData)->hWMIconBitmap );
459 ((X11DRV_WND_DATA *) wndPtr->pDriverData)->hWMIconBitmap = 0;
461 if( ((X11DRV_WND_DATA *) wndPtr->pDriverData)->hWMIconMask )
463 DeleteObject( ((X11DRV_WND_DATA *) wndPtr->pDriverData)->hWMIconMask);
464 ((X11DRV_WND_DATA *) wndPtr->pDriverData)->hWMIconMask= 0;
468 return TRUE;
471 /*****************************************************************
472 * X11DRV_WND_SetParent
474 WND *X11DRV_WND_SetParent(WND *wndPtr, WND *pWndParent)
476 WND *pDesktop = WIN_GetDesktop();
478 if( wndPtr && pWndParent && (wndPtr != pDesktop) )
480 WND* pWndPrev = wndPtr->parent;
482 if( pWndParent != pWndPrev )
484 if ( X11DRV_WND_GetXWindow(wndPtr) )
486 /* Toplevel window needs to be reparented. Used by Tk 8.0 */
488 TSXDestroyWindow( display, X11DRV_WND_GetXWindow(wndPtr) );
489 ((X11DRV_WND_DATA *) wndPtr->pDriverData)->window = None;
492 WIN_UnlinkWindow(wndPtr->hwndSelf);
493 wndPtr->parent = pWndParent;
495 /* Create an X counterpart for reparented top-level windows
496 * when not in the desktop mode. */
498 if( pWndParent == pDesktop )
500 if( X11DRV_GetXRootWindow() == DefaultRootWindow(display) )
502 CREATESTRUCTA cs;
503 cs.lpCreateParams = NULL;
504 cs.hInstance = 0; /* not used in following call */
505 cs.hMenu = 0; /* not used in following call */
506 cs.hwndParent = pWndParent->hwndSelf;
507 cs.cy = wndPtr->rectWindow.bottom - wndPtr->rectWindow.top;
508 if (!cs.cy)
509 cs.cy = 1;
510 cs.cx = wndPtr->rectWindow.right - wndPtr->rectWindow.left;
511 if (!cs.cx)
512 cs.cx = 1;
513 cs.y = wndPtr->rectWindow.top;
514 cs.x = wndPtr->rectWindow.left;
515 cs.style = wndPtr->dwStyle;
516 cs.lpszName = 0; /* not used in following call */
517 cs.lpszClass = 0; /*not used in following call */
518 cs.dwExStyle = wndPtr->dwExStyle;
519 X11DRV_WND_CreateWindow(wndPtr, &cs, FALSE);
522 else /* a child window */
524 if( !( wndPtr->dwStyle & WS_CHILD ) )
526 if( wndPtr->wIDmenu != 0)
528 DestroyMenu( (HMENU) wndPtr->wIDmenu );
529 wndPtr->wIDmenu = 0;
533 WIN_LinkWindow(wndPtr->hwndSelf, HWND_TOP);
535 WIN_ReleaseDesktop();
536 return pWndPrev;
537 } /* failure */
538 WIN_ReleaseDesktop();
539 return 0;
542 /***********************************************************************
543 * X11DRV_WND_ForceWindowRaise
545 * Raise a window on top of the X stacking order, while preserving
546 * the correct Windows Z order.
548 void X11DRV_WND_ForceWindowRaise(WND *wndPtr)
550 XWindowChanges winChanges;
551 WND *wndPrev,*pDesktop = WIN_GetDesktop();
553 if (X11DRV_WND_IsZeroSizeWnd(wndPtr))
555 WIN_ReleaseDesktop();
556 return;
559 if( !wndPtr || !X11DRV_WND_GetXWindow(wndPtr) || (wndPtr->dwExStyle & WS_EX_MANAGED) )
561 WIN_ReleaseDesktop();
562 return;
565 /* Raise all windows up to wndPtr according to their Z order.
566 * (it would be easier with sibling-related Below but it doesn't
567 * work very well with SGI mwm for instance)
569 winChanges.stack_mode = Above;
570 while (wndPtr)
572 if ( !X11DRV_WND_IsZeroSizeWnd(wndPtr) && X11DRV_WND_GetXWindow(wndPtr) )
573 TSXReconfigureWMWindow( display, X11DRV_WND_GetXWindow(wndPtr), 0,
574 CWStackMode, &winChanges );
576 wndPrev = pDesktop->child;
577 if (wndPrev == wndPtr) break;
578 while (wndPrev && (wndPrev->next != wndPtr)) wndPrev = wndPrev->next;
580 wndPtr = wndPrev;
582 WIN_ReleaseDesktop();
585 /***********************************************************************
586 * X11DRV_WND_FindDesktopXWindow [Internal]
588 * Find the actual X window which needs be restacked.
589 * Used by X11DRV_WND_SetWindowPos().
591 static Window X11DRV_WND_FindDesktopXWindow( WND *wndPtr )
593 if (!(wndPtr->dwExStyle & WS_EX_MANAGED))
594 return X11DRV_WND_GetXWindow(wndPtr);
595 else
597 Window window, root, parent, *children;
598 int nchildren;
599 window = X11DRV_WND_GetXWindow(wndPtr);
600 for (;;)
602 TSXQueryTree( display, window, &root, &parent,
603 &children, &nchildren );
604 TSXFree( children );
605 if (parent == root)
606 return window;
607 window = parent;
612 /***********************************************************************
613 * WINPOS_SetXWindowPos
615 * SetWindowPos() for an X window. Used by the real SetWindowPos().
617 void X11DRV_WND_SetWindowPos(WND *wndPtr, const WINDOWPOS *winpos, BOOL bChangePos)
619 XWindowChanges winChanges;
620 int changeMask = 0;
621 BOOL isZeroSizeWnd = FALSE;
622 BOOL forceMapWindow = FALSE;
623 WND *winposPtr = WIN_FindWndPtr( winpos->hwnd );
624 if ( !winposPtr ) return;
626 /* find out if after this function we will end out with a zero-size window */
627 if (X11DRV_WND_IsZeroSizeWnd(winposPtr))
629 /* if current size is 0, and no resizing */
630 if (winpos->flags & SWP_NOSIZE)
631 isZeroSizeWnd = TRUE;
632 else if ((winpos->cx > 0) && (winpos->cy > 0))
634 /* if this function is setting a new size > 0 for the window, we
635 should map the window if WS_VISIBLE is set */
636 if ((winposPtr->dwStyle & WS_VISIBLE) && !(winpos->flags & SWP_HIDEWINDOW))
637 forceMapWindow = TRUE;
640 /* if resizing to 0 */
641 if ( !(winpos->flags & SWP_NOSIZE) && ((winpos->cx <= 0) || (winpos->cy <= 0)) )
642 isZeroSizeWnd = TRUE;
644 if(!wndPtr->hwndSelf) wndPtr = NULL; /* FIXME: WND destroyed, shouldn't happen!!! */
646 if (!(winpos->flags & SWP_SHOWWINDOW) && (winpos->flags & SWP_HIDEWINDOW))
648 if(X11DRV_WND_GetXWindow(wndPtr))
649 TSXUnmapWindow( display, X11DRV_WND_GetXWindow(wndPtr) );
652 if(bChangePos)
654 if ( !(winpos->flags & SWP_NOSIZE))
656 winChanges.width = (winpos->cx > 0 ) ? winpos->cx : 1;
657 winChanges.height = (winpos->cy > 0 ) ? winpos->cy : 1;
658 changeMask |= CWWidth | CWHeight;
660 /* Tweak dialog window size hints */
662 if ((winposPtr->dwExStyle & WS_EX_MANAGED) &&
663 HAS_DLGFRAME(winposPtr->dwStyle,winposPtr->dwExStyle))
665 XSizeHints *size_hints = TSXAllocSizeHints();
667 if (size_hints)
669 long supplied_return;
671 TSXGetWMSizeHints( display, X11DRV_WND_GetXWindow(winposPtr), size_hints,
672 &supplied_return, XA_WM_NORMAL_HINTS);
673 size_hints->min_width = size_hints->max_width = winpos->cx;
674 size_hints->min_height = size_hints->max_height = winpos->cy;
675 TSXSetWMSizeHints( display, X11DRV_WND_GetXWindow(winposPtr), size_hints,
676 XA_WM_NORMAL_HINTS );
677 TSXFree(size_hints);
681 if (!(winpos->flags & SWP_NOMOVE))
683 winChanges.x = winpos->x;
684 winChanges.y = winpos->y;
685 changeMask |= CWX | CWY;
687 if (!(winpos->flags & SWP_NOZORDER) && !isZeroSizeWnd)
689 winChanges.stack_mode = Below;
690 changeMask |= CWStackMode;
692 if (winpos->hwndInsertAfter == HWND_TOP) winChanges.stack_mode = Above;
693 else if (winpos->hwndInsertAfter != HWND_BOTTOM)
695 WND* insertPtr = WIN_FindWndPtr( winpos->hwndInsertAfter );
696 Window stack[2];
698 /* If the window where we should do the insert is zero-sized (not mapped)
699 don't used this window since it will possibly crash the X server,
700 use the "non zero-sized" window above */
701 if (X11DRV_WND_IsZeroSizeWnd(insertPtr))
703 /* find the window on top of the zero sized window */
704 WND *pDesktop = WIN_GetDesktop();
705 WND *wndPrev = pDesktop->child;
706 WND *wndZeroSized = insertPtr;
708 while (1)
710 if (wndPrev == wndZeroSized)
711 break; /* zero-sized window is on top */
713 while (wndPrev && (wndPrev->next != wndZeroSized))
714 wndPrev = wndPrev->next;
716 /* check if the window found is not zero-sized */
717 if (X11DRV_WND_IsZeroSizeWnd(wndPrev))
719 wndZeroSized = wndPrev; /* restart the search */
720 wndPrev = pDesktop->child;
722 else
723 break; /* "above" window is found */
725 WIN_ReleaseDesktop();
727 if (wndPrev == wndZeroSized)
729 /* the zero-sized window is on top */
730 /* so set the window on top */
731 winChanges.stack_mode = Above;
733 else
735 stack[0] = X11DRV_WND_FindDesktopXWindow( wndPrev );
736 stack[1] = X11DRV_WND_FindDesktopXWindow( winposPtr );
738 TSXRestackWindows(display, stack, 2);
739 changeMask &= ~CWStackMode;
742 else /* Normal behavior, windows are not zero-sized */
744 stack[0] = X11DRV_WND_FindDesktopXWindow( insertPtr );
745 stack[1] = X11DRV_WND_FindDesktopXWindow( winposPtr );
747 TSXRestackWindows(display, stack, 2);
748 changeMask &= ~CWStackMode;
751 WIN_ReleaseWndPtr(insertPtr);
754 if (changeMask && X11DRV_WND_GetXWindow(winposPtr))
756 TSXReconfigureWMWindow( display, X11DRV_WND_GetXWindow(winposPtr), 0, changeMask, &winChanges );
757 if( winposPtr->clsStyle & (CS_VREDRAW | CS_HREDRAW) )
758 X11DRV_WND_SetHostAttr( winposPtr, HAK_BITGRAVITY, BGForget );
762 /* don't map the window if it's a zero size window */
763 if ( ((winpos->flags & SWP_SHOWWINDOW) && !isZeroSizeWnd) || forceMapWindow )
765 if(X11DRV_WND_GetXWindow(wndPtr))
766 TSXMapWindow( display, X11DRV_WND_GetXWindow(wndPtr) );
768 WIN_ReleaseWndPtr(winposPtr);
771 /*****************************************************************
772 * X11DRV_WND_SetText
774 void X11DRV_WND_SetText(WND *wndPtr, LPCWSTR text)
776 UINT count;
777 char *buffer;
778 static UINT text_cp = (UINT)-1;
779 Window win;
781 if (!(win = X11DRV_WND_GetXWindow(wndPtr))) return;
783 if(text_cp == (UINT)-1)
785 text_cp = PROFILE_GetWineIniInt("x11drv", "TextCP", CP_ACP);
786 TRACE("text_cp = %u\n", text_cp);
789 /* allocate new buffer for window text */
790 count = WideCharToMultiByte(text_cp, 0, text, -1, NULL, 0, NULL, NULL);
791 if (!(buffer = HeapAlloc( GetProcessHeap(), 0, count * sizeof(WCHAR) )))
793 ERR("Not enough memory for window text\n");
794 return;
796 WideCharToMultiByte(text_cp, 0, text, -1, buffer, count, NULL, NULL);
798 TSXStoreName( display, win, buffer );
799 TSXSetIconName( display, win, buffer );
800 HeapFree( GetProcessHeap(), 0, buffer );
803 /*****************************************************************
804 * X11DRV_WND_SetFocus
806 * Set the X focus.
807 * Explicit colormap management seems to work only with OLVWM.
809 void X11DRV_WND_SetFocus(WND *wndPtr)
811 HWND hwnd = wndPtr->hwndSelf;
812 XWindowAttributes win_attr;
813 Window win;
814 WND *w = wndPtr;
816 if (X11DRV_WND_IsZeroSizeWnd(wndPtr))
817 return;
819 /* Only mess with the X focus if there's */
820 /* no desktop window and if the window is not managed by the WM. */
821 if ((X11DRV_GetXRootWindow() != DefaultRootWindow(display))) return;
822 while (w && !((X11DRV_WND_DATA *) w->pDriverData)->window)
823 w = w->parent;
824 if (!w) w = wndPtr;
825 if (w->dwExStyle & WS_EX_MANAGED) return;
827 if (!hwnd) /* If setting the focus to 0, uninstall the colormap */
829 if (X11DRV_PALETTE_PaletteFlags & X11DRV_PALETTE_PRIVATE)
830 TSXUninstallColormap( display, X11DRV_PALETTE_PaletteXColormap );
831 return;
834 /* Set X focus and install colormap */
836 if (!(win = X11DRV_WND_FindXWindow(wndPtr))) return;
837 if (!TSXGetWindowAttributes( display, win, &win_attr ) ||
838 (win_attr.map_state != IsViewable))
839 return; /* If window is not viewable, don't change anything */
841 TSXSetInputFocus( display, win, RevertToParent, CurrentTime );
842 if (X11DRV_PALETTE_PaletteFlags & X11DRV_PALETTE_PRIVATE)
843 TSXInstallColormap( display, X11DRV_PALETTE_PaletteXColormap );
845 EVENT_Synchronize();
848 /*****************************************************************
849 * X11DRV_WND_PreSizeMove
851 void X11DRV_WND_PreSizeMove(WND *wndPtr)
853 /* Grab the server only when moving top-level windows without desktop */
854 if (!(wndPtr->dwStyle & WS_CHILD) && (X11DRV_GetXRootWindow() == DefaultRootWindow(display)))
855 TSXGrabServer( display );
858 /*****************************************************************
859 * X11DRV_WND_PostSizeMove
861 void X11DRV_WND_PostSizeMove(WND *wndPtr)
863 if (!(wndPtr->dwStyle & WS_CHILD) &&
864 (X11DRV_GetXRootWindow() == DefaultRootWindow(display)))
865 TSXUngrabServer( display );
868 /*****************************************************************
869 * X11DRV_WND_SurfaceCopy
871 * Copies rect to (rect.left + dx, rect.top + dy).
873 void X11DRV_WND_SurfaceCopy(WND* wndPtr, HDC hdc, INT dx, INT dy,
874 const RECT *rect, BOOL bUpdate)
876 X11DRV_PDEVICE *physDev;
877 POINT dst, src;
878 DC *dcPtr = DC_GetDCPtr( hdc );
880 if (!dcPtr) return;
881 physDev = (X11DRV_PDEVICE *)dcPtr->physDev;
882 dst.x = (src.x = dcPtr->DCOrgX + rect->left) + dx;
883 dst.y = (src.y = dcPtr->DCOrgY + rect->top) + dy;
885 if (bUpdate) /* handles non-Wine windows hanging over the copied area */
886 TSXSetGraphicsExposures( display, physDev->gc, True );
887 TSXSetFunction( display, physDev->gc, GXcopy );
888 TSXCopyArea( display, physDev->drawable, physDev->drawable,
889 physDev->gc, src.x, src.y,
890 rect->right - rect->left,
891 rect->bottom - rect->top,
892 dst.x, dst.y );
893 if (bUpdate)
894 TSXSetGraphicsExposures( display, physDev->gc, False );
895 GDI_ReleaseObj( hdc );
897 if (bUpdate) /* Make sure exposure events have been processed */
898 EVENT_Synchronize();
901 /***********************************************************************
902 * X11DRV_WND_SetDrawable
904 * Set the drawable, origin and dimensions for the DC associated to
905 * a given window.
907 void X11DRV_WND_SetDrawable(WND *wndPtr, HDC hdc, WORD flags, BOOL bSetClipOrigin)
909 DC *dc = DC_GetDCPtr( hdc );
910 X11DRV_PDEVICE *physDev;
911 INT dcOrgXCopy = 0, dcOrgYCopy = 0;
912 BOOL offsetClipRgn = FALSE;
914 if (!dc) return;
915 physDev = (X11DRV_PDEVICE *)dc->physDev;
916 if (!wndPtr) /* Get a DC for the whole screen */
918 dc->DCOrgX = 0;
919 dc->DCOrgY = 0;
920 physDev->drawable = X11DRV_GetXRootWindow();
921 TSXSetSubwindowMode( display, physDev->gc, IncludeInferiors );
923 else
926 * This function change the coordinate system (DCOrgX,DCOrgY)
927 * values. When it moves the origin, other data like the current clipping
928 * region will not be moved to that new origin. In the case of DCs that are class
929 * or window DCs that clipping region might be a valid value from a previous use
930 * of the DC and changing the origin of the DC without moving the clip region
931 * results in a clip region that is not placed properly in the DC.
932 * This code will save the dc origin, let the SetDrawable
933 * modify the origin and reset the clipping. When the clipping is set,
934 * it is moved according to the new DC origin.
936 if ( (wndPtr->clsStyle & (CS_OWNDC | CS_CLASSDC)) && (dc->hClipRgn > 0))
938 dcOrgXCopy = dc->DCOrgX;
939 dcOrgYCopy = dc->DCOrgY;
940 offsetClipRgn = TRUE;
943 if (flags & DCX_WINDOW)
945 dc->DCOrgX = wndPtr->rectWindow.left;
946 dc->DCOrgY = wndPtr->rectWindow.top;
948 else
950 dc->DCOrgX = wndPtr->rectClient.left;
951 dc->DCOrgY = wndPtr->rectClient.top;
953 while (!X11DRV_WND_GetXWindow(wndPtr))
955 wndPtr = wndPtr->parent;
956 dc->DCOrgX += wndPtr->rectClient.left;
957 dc->DCOrgY += wndPtr->rectClient.top;
959 dc->DCOrgX -= wndPtr->rectWindow.left;
960 dc->DCOrgY -= wndPtr->rectWindow.top;
962 /* reset the clip region, according to the new origin */
963 if ( offsetClipRgn )
965 OffsetRgn(dc->hClipRgn, dc->DCOrgX - dcOrgXCopy,dc->DCOrgY - dcOrgYCopy);
968 physDev->drawable = X11DRV_WND_GetXWindow(wndPtr);
970 #if 0
971 /* This is needed when we reuse a cached DC because
972 * SetDCState() called by ReleaseDC() screws up DC
973 * origins for child windows.
976 if( bSetClipOrigin )
977 TSXSetClipOrigin( display, physDev->gc, dc->DCOrgX, dc->DCOrgY );
978 #endif
980 GDI_ReleaseObj( hdc );
983 /***********************************************************************
984 * X11DRV_SetWMHint
986 static BOOL X11DRV_SetWMHint(Display* display, WND* wndPtr, int hint, int val)
988 XWMHints* wm_hints = TSXGetWMHints( display, X11DRV_WND_GetXWindow(wndPtr) );
989 if (!wm_hints) wm_hints = TSXAllocWMHints();
990 if (wm_hints)
992 wm_hints->flags = hint;
993 switch( hint )
995 case InputHint:
996 wm_hints->input = val;
997 break;
999 case StateHint:
1000 wm_hints->initial_state = val;
1001 break;
1003 case IconPixmapHint:
1004 wm_hints->icon_pixmap = (Pixmap)val;
1005 break;
1007 case IconWindowHint:
1008 wm_hints->icon_window = (Window)val;
1009 break;
1012 TSXSetWMHints( display, X11DRV_WND_GetXWindow(wndPtr), wm_hints );
1013 TSXFree(wm_hints);
1014 return TRUE;
1016 return FALSE;
1020 /***********************************************************************
1021 * X11DRV_WND_SetHostAttr
1023 * This function returns TRUE if the attribute is supported and the
1024 * action was successful. Otherwise it should return FALSE and Wine will try
1025 * to get by without the functionality provided by the host window system.
1027 BOOL X11DRV_WND_SetHostAttr(WND* wnd, INT ha, INT value)
1029 Window w;
1031 if( (w = X11DRV_WND_GetXWindow(wnd)) )
1033 XSetWindowAttributes win_attr;
1035 switch( ha )
1037 case HAK_ICONICSTATE: /* called when a window is minimized/restored */
1039 /* don't do anything if it'a zero size window */
1040 if (X11DRV_WND_IsZeroSizeWnd(wnd))
1041 return TRUE;
1043 if( (wnd->dwExStyle & WS_EX_MANAGED) )
1045 if( value )
1047 if( wnd->dwStyle & WS_VISIBLE )
1049 XClientMessageEvent ev;
1051 /* FIXME: set proper icon */
1053 ev.type = ClientMessage;
1054 ev.display = display;
1055 ev.message_type = wmChangeState;
1056 ev.format = 32;
1057 ev.data.l[0] = IconicState;
1058 ev.window = w;
1060 if( TSXSendEvent (display,
1061 RootWindow( display, XScreenNumberOfScreen(X11DRV_GetXScreen()) ),
1062 True, (SubstructureRedirectMask | SubstructureNotifyMask), (XEvent*)&ev))
1064 XEvent xe;
1065 TSXFlush (display);
1066 while( !TSXCheckTypedWindowEvent( display, w, UnmapNotify, &xe) );
1068 else
1069 break;
1071 else
1072 X11DRV_SetWMHint( display, wnd, StateHint, IconicState );
1074 else
1076 if( !(wnd->flags & WS_VISIBLE) )
1077 X11DRV_SetWMHint( display, wnd, StateHint, NormalState );
1078 else
1080 XEvent xe;
1081 TSXMapWindow(display, w );
1082 while( !TSXCheckTypedWindowEvent( display, w, MapNotify, &xe) );
1085 return TRUE;
1087 break;
1089 case HAK_BITGRAVITY: /* called when a window is resized */
1091 if( ((X11DRV_WND_DATA *) wnd->pDriverData)->bit_gravity != value )
1093 win_attr.bit_gravity = value;
1094 ((X11DRV_WND_DATA *) wnd->pDriverData)->bit_gravity = value;
1095 TSXChangeWindowAttributes( display, w, CWBitGravity, &win_attr );
1097 return TRUE;
1099 case HAK_ICONS: /* called when the icons change */
1100 if ( (wnd->dwExStyle & WS_EX_MANAGED) )
1101 X11DRV_WND_UpdateIconHints(wnd);
1102 return TRUE;
1104 case HAK_ACCEPTFOCUS: /* called when a window is disabled/enabled */
1106 if( (wnd->dwExStyle & WS_EX_MANAGED) )
1107 return X11DRV_SetWMHint( display, wnd, InputHint, value );
1110 return FALSE;
1113 /***********************************************************************
1114 * X11DRV_WND_IsSelfClipping
1116 BOOL X11DRV_WND_IsSelfClipping(WND *wndPtr)
1118 return X11DRV_WND_GetXWindow(wndPtr) != None;
1121 /***********************************************************************
1122 * X11DRV_WND_DockWindow
1124 * Set the X Property of the window that tells the windowmanager we really
1125 * want to be in the systray
1127 * KDE: set "KWM_DOCKWINDOW", type "KWM_DOCKWINDOW" to 1 before a window is
1128 * mapped.
1130 * all others: to be added ;)
1132 void X11DRV_WND_DockWindow(WND *wndPtr)
1134 int data = 1;
1135 Window win = X11DRV_WND_GetXWindow(wndPtr);
1136 if (kwmDockWindow != None) {
1137 TSXChangeProperty(
1138 display,win,kwmDockWindow,kwmDockWindow,32,PropModeReplace,(char*)&data,1
1141 if (_kde_net_wm_system_tray_window_for != None) {
1142 TSXChangeProperty(
1143 display,
1144 win,
1145 _kde_net_wm_system_tray_window_for,
1146 XA_WINDOW,
1148 PropModeReplace,
1149 (char*)&win,
1153 if (_net_kde_system_tray_window_for != None) {
1154 TSXChangeProperty(
1155 display,
1156 win,
1157 _net_kde_system_tray_window_for,
1158 XA_WINDOW,
1160 PropModeReplace,
1161 (char*)&win,
1169 /***********************************************************************
1170 * X11DRV_WND_SetWindowRgn
1172 * Assign specified region to window (for non-rectangular windows)
1174 void X11DRV_WND_SetWindowRgn(WND *wndPtr, HRGN hrgnWnd)
1176 #ifdef HAVE_LIBXSHAPE
1177 Window win = X11DRV_WND_GetXWindow(wndPtr);
1179 if (!win) return;
1181 if (!hrgnWnd)
1183 TSXShapeCombineMask( display, win, ShapeBounding, 0, 0, None, ShapeSet );
1185 else
1187 XRectangle *aXRect;
1188 DWORD size;
1189 DWORD dwBufferSize = GetRegionData(hrgnWnd, 0, NULL);
1190 PRGNDATA pRegionData = HeapAlloc(GetProcessHeap(), 0, dwBufferSize);
1191 if (!pRegionData) return;
1193 GetRegionData(hrgnWnd, dwBufferSize, pRegionData);
1194 size = pRegionData->rdh.nCount;
1195 /* convert region's "Windows rectangles" to XRectangles */
1196 aXRect = HeapAlloc(GetProcessHeap(), 0, size * sizeof(*aXRect) );
1197 if (aXRect)
1199 XRectangle* pCurrRect = aXRect;
1200 RECT *pRect = (RECT*) pRegionData->Buffer;
1201 for (; pRect < ((RECT*) pRegionData->Buffer) + size ; ++pRect, ++pCurrRect)
1203 pCurrRect->x = pRect->left;
1204 pCurrRect->y = pRect->top;
1205 pCurrRect->height = pRect->bottom - pRect->top;
1206 pCurrRect->width = pRect->right - pRect->left;
1208 TRACE("Rectangle %04d of %04ld data: X=%04d, Y=%04d, Height=%04d, Width=%04d.\n",
1209 pRect - (RECT*) pRegionData->Buffer,
1210 size,
1211 pCurrRect->x,
1212 pCurrRect->y,
1213 pCurrRect->height,
1214 pCurrRect->width);
1217 /* shape = non-rectangular windows (X11/extensions) */
1218 TSXShapeCombineRectangles( display, win, ShapeBounding,
1219 0, 0, aXRect,
1220 pCurrRect - aXRect, ShapeSet, YXBanded );
1221 HeapFree(GetProcessHeap(), 0, aXRect );
1223 HeapFree(GetProcessHeap(), 0, pRegionData);
1225 #endif /* HAVE_LIBXSHAPE */