Fix prototypes of MSVCRT___getmainargs and MSVCRT___wgetmainargs.
[wine.git] / windows / x11drv / wnd.c
blobc0cdc1034261a879559934c57d0f3e888d1428e9
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 "heap.h"
26 #include "win.h"
27 #include "windef.h"
28 #include "x11drv.h"
29 #include "wingdi.h"
30 #include "winnls.h"
31 #include "wine/winuser16.h"
33 DEFAULT_DEBUG_CHANNEL(win);
35 /* Some useful macros */
36 #define HAS_DLGFRAME(style,exStyle) \
37 ((!((style) & WS_THICKFRAME)) && (((style) & WS_DLGFRAME) || ((exStyle) & WS_EX_DLGMODALFRAME)))
39 /**********************************************************************/
41 extern Cursor X11DRV_MOUSE_XCursor; /* Current X cursor */
42 extern BOOL X11DRV_CreateBitmap( HBITMAP );
43 extern Pixmap X11DRV_BITMAP_Pixmap( HBITMAP );
45 /**********************************************************************/
47 WND_DRIVER X11DRV_WND_Driver =
49 X11DRV_WND_Initialize,
50 X11DRV_WND_Finalize,
51 X11DRV_WND_CreateDesktopWindow,
52 X11DRV_WND_CreateWindow,
53 X11DRV_WND_DestroyWindow,
54 X11DRV_WND_SetParent,
55 X11DRV_WND_ForceWindowRaise,
56 X11DRV_WND_SetWindowPos,
57 X11DRV_WND_SetText,
58 X11DRV_WND_SetFocus,
59 X11DRV_WND_PreSizeMove,
60 X11DRV_WND_PostSizeMove,
61 X11DRV_WND_SurfaceCopy,
62 X11DRV_WND_SetDrawable,
63 X11DRV_WND_SetHostAttr,
64 X11DRV_WND_IsSelfClipping,
65 X11DRV_WND_SetWindowRgn
69 /* X context to associate a hwnd to an X window */
70 XContext winContext = 0;
72 Atom wmProtocols = None;
73 Atom wmDeleteWindow = None;
74 Atom dndProtocol = None;
75 Atom dndSelection = None;
76 Atom wmChangeState = None;
78 Atom kwmDockWindow = None;
79 Atom _net_kde_system_tray_window_for = None; /* KDE 2 Beta */
80 Atom _kde_net_wm_system_tray_window_for = None; /* KDE 2 Final */
82 /***********************************************************************
83 * X11DRV_WND_GetXWindow
85 * Return the X window associated to a window.
87 Window X11DRV_WND_GetXWindow(WND *wndPtr)
89 return wndPtr && wndPtr->pDriverData ?
90 ((X11DRV_WND_DATA *) wndPtr->pDriverData)->window : 0;
93 /***********************************************************************
94 * X11DRV_WND_FindXWindow
96 * Return the the first X window associated to a window chain.
98 Window X11DRV_WND_FindXWindow(WND *wndPtr)
100 while (wndPtr &&
101 !((X11DRV_WND_DATA *) wndPtr->pDriverData)->window)
102 wndPtr = wndPtr->parent;
103 return wndPtr ?
104 ((X11DRV_WND_DATA *) wndPtr->pDriverData)->window : 0;
107 /***********************************************************************
108 * X11DRV_WND_RegisterWindow
110 * Associate an X window to a HWND.
112 static void X11DRV_WND_RegisterWindow(WND *wndPtr)
114 TSXSetWMProtocols( display, X11DRV_WND_GetXWindow(wndPtr), &wmDeleteWindow, 1 );
116 if (!winContext) winContext = TSXUniqueContext();
117 TSXSaveContext( display, X11DRV_WND_GetXWindow(wndPtr),
118 winContext, (char *) wndPtr->hwndSelf );
121 /***********************************************************************
122 * X11DRV_WND_IsZeroSizeWnd
124 * Return TRUE if the window has a height or widht less or equal to 0
126 static BOOL X11DRV_WND_IsZeroSizeWnd(WND *wndPtr)
128 if ( (wndPtr->rectWindow.left >= wndPtr->rectWindow.right) ||
129 (wndPtr->rectWindow.top >= wndPtr->rectWindow.bottom) )
130 return TRUE;
131 else
132 return FALSE;
135 /**********************************************************************
136 * X11DRV_WND_Initialize
138 void X11DRV_WND_Initialize(WND *wndPtr)
140 X11DRV_WND_DATA *pWndDriverData =
141 (X11DRV_WND_DATA *) HeapAlloc(SystemHeap, 0, sizeof(X11DRV_WND_DATA));
143 wndPtr->pDriverData = (void *) pWndDriverData;
145 pWndDriverData->window = 0;
148 /**********************************************************************
149 * X11DRV_WND_Finalize
151 void X11DRV_WND_Finalize(WND *wndPtr)
153 X11DRV_WND_DATA *pWndDriverData =
154 (X11DRV_WND_DATA *) wndPtr->pDriverData;
156 if (!wndPtr->pDriverData) {
157 ERR("Trying to destroy window again. Not good.\n");
158 return;
160 if(pWndDriverData->window)
162 ERR(
163 "WND destroyed without destroying "
164 "the associated X Window (%ld)\n",
165 pWndDriverData->window
168 HeapFree(SystemHeap, 0, wndPtr->pDriverData);
169 wndPtr->pDriverData = NULL;
172 /**********************************************************************
173 * X11DRV_WND_CreateDesktopWindow
175 BOOL X11DRV_WND_CreateDesktopWindow(WND *wndPtr)
177 if (wmProtocols == None)
178 wmProtocols = TSXInternAtom( display, "WM_PROTOCOLS", True );
179 if (wmDeleteWindow == None)
180 wmDeleteWindow = TSXInternAtom( display, "WM_DELETE_WINDOW", True );
181 if( dndProtocol == None )
182 dndProtocol = TSXInternAtom( display, "DndProtocol" , False );
183 if( dndSelection == None )
184 dndSelection = TSXInternAtom( display, "DndSelection" , False );
185 if( wmChangeState == None )
186 wmChangeState = TSXInternAtom (display, "WM_CHANGE_STATE", False);
187 if (kwmDockWindow == None)
188 kwmDockWindow = TSXInternAtom( display, "KWM_DOCKWINDOW", False );
189 if (_kde_net_wm_system_tray_window_for == None)
190 _kde_net_wm_system_tray_window_for = TSXInternAtom( display, "_KDE_NET_WM_SYSTEM_TRAY_WINDOW_FOR", False );
191 if (_net_kde_system_tray_window_for == None)
192 _net_kde_system_tray_window_for = TSXInternAtom( display, "_NET_KDE_SYSTEM_TRAY_WINDOW_FOR", False );
194 ((X11DRV_WND_DATA *) wndPtr->pDriverData)->window = X11DRV_GetXRootWindow();
195 X11DRV_WND_RegisterWindow( wndPtr );
197 return TRUE;
200 /**********************************************************************
201 * X11DRV_WND_IconChanged
203 * hIcon or hIconSm has changed (or is being initialised for the
204 * first time). Complete the X11 driver-specific initialisation.
206 * This is not entirely correct, may need to create
207 * an icon window and set the pixmap as a background
209 static void X11DRV_WND_IconChanged(WND *wndPtr)
212 HICON16 hIcon = NC_IconForWindow(wndPtr);
214 if( ((X11DRV_WND_DATA *) wndPtr->pDriverData)->hWMIconBitmap )
215 DeleteObject( ((X11DRV_WND_DATA *) wndPtr->pDriverData)->hWMIconBitmap );
217 if( ((X11DRV_WND_DATA *) wndPtr->pDriverData)->hWMIconMask )
218 DeleteObject( ((X11DRV_WND_DATA *) wndPtr->pDriverData)->hWMIconMask);
220 if (!hIcon)
222 ((X11DRV_WND_DATA *) wndPtr->pDriverData)->hWMIconBitmap= 0;
223 ((X11DRV_WND_DATA *) wndPtr->pDriverData)->hWMIconMask= 0;
225 else
227 HBITMAP hbmOrig;
228 RECT rcMask;
229 BITMAP bmMask;
230 ICONINFO ii;
231 HDC hDC;
233 GetIconInfo(hIcon, &ii);
235 X11DRV_CreateBitmap(ii.hbmMask);
236 X11DRV_CreateBitmap(ii.hbmColor);
238 GetObjectA(ii.hbmMask, sizeof(bmMask), &bmMask);
239 rcMask.top = 0;
240 rcMask.left = 0;
241 rcMask.right = bmMask.bmWidth;
242 rcMask.bottom = bmMask.bmHeight;
244 hDC = CreateCompatibleDC(0);
245 hbmOrig = SelectObject(hDC, ii.hbmMask);
246 InvertRect(hDC, &rcMask);
247 SelectObject(hDC, hbmOrig);
248 DeleteDC(hDC);
250 ((X11DRV_WND_DATA *) wndPtr->pDriverData)->hWMIconBitmap = ii.hbmColor;
251 ((X11DRV_WND_DATA *) wndPtr->pDriverData)->hWMIconMask= ii.hbmMask;
253 return;
256 static void X11DRV_WND_SetIconHints(WND *wndPtr, XWMHints *hints)
258 if (((X11DRV_WND_DATA *) wndPtr->pDriverData)->hWMIconBitmap)
260 hints->icon_pixmap
261 = X11DRV_BITMAP_Pixmap(((X11DRV_WND_DATA *) wndPtr->pDriverData)->hWMIconBitmap);
262 hints->flags |= IconPixmapHint;
264 else
265 hints->flags &= ~IconPixmapHint;
267 if (((X11DRV_WND_DATA *) wndPtr->pDriverData)->hWMIconMask)
269 hints->icon_mask
270 = X11DRV_BITMAP_Pixmap(((X11DRV_WND_DATA *) wndPtr->pDriverData)->hWMIconMask);
271 hints->flags |= IconMaskHint;
273 else
274 hints->flags &= ~IconMaskHint;
277 /**********************************************************************
278 * X11DRV_WND_UpdateIconHints
280 * hIcon or hIconSm has changed (or is being initialised for the
281 * first time). Complete the X11 driver-specific initialisation
282 * and set the window hints.
284 * This is not entirely correct, may need to create
285 * an icon window and set the pixmap as a background
287 static void X11DRV_WND_UpdateIconHints(WND *wndPtr)
289 XWMHints* wm_hints;
291 X11DRV_WND_IconChanged(wndPtr);
293 wm_hints = TSXGetWMHints( display, X11DRV_WND_GetXWindow(wndPtr) );
294 if (!wm_hints) wm_hints = TSXAllocWMHints();
295 if (wm_hints)
297 X11DRV_WND_SetIconHints(wndPtr, wm_hints);
298 TSXSetWMHints( display, X11DRV_WND_GetXWindow(wndPtr), wm_hints );
299 TSXFree( wm_hints );
304 /**********************************************************************
305 * X11DRV_WND_CreateWindow
307 BOOL X11DRV_WND_CreateWindow(WND *wndPtr, CREATESTRUCTA *cs, BOOL bUnicode)
309 /* Create the X window (only for top-level windows, and then only */
310 /* when there's no desktop window) */
312 if ((X11DRV_GetXRootWindow() == DefaultRootWindow(display))
313 && (wndPtr->parent->hwndSelf == GetDesktopWindow()))
315 Window wGroupLeader;
316 XWMHints* wm_hints;
317 XSetWindowAttributes win_attr;
319 /* Create "managed" windows only if a title bar or resizable */
320 /* frame is required. */
321 if (WIN_WindowNeedsWMBorder(cs->style, cs->dwExStyle)) {
322 win_attr.event_mask = ExposureMask | KeyPressMask |
323 KeyReleaseMask | PointerMotionMask |
324 ButtonPressMask | ButtonReleaseMask |
325 FocusChangeMask | StructureNotifyMask;
326 win_attr.override_redirect = FALSE;
327 wndPtr->dwExStyle |= WS_EX_MANAGED;
328 } else {
329 win_attr.event_mask = ExposureMask | KeyPressMask |
330 KeyReleaseMask | PointerMotionMask |
331 ButtonPressMask | ButtonReleaseMask |
332 FocusChangeMask;
333 win_attr.override_redirect = TRUE;
335 wndPtr->flags |= WIN_NATIVE;
337 win_attr.bit_gravity = (wndPtr->clsStyle & (CS_VREDRAW | CS_HREDRAW)) ? BGForget : BGNorthWest;
338 win_attr.colormap = X11DRV_PALETTE_PaletteXColormap;
339 win_attr.backing_store = NotUseful;
340 win_attr.save_under = ((wndPtr->clsStyle & CS_SAVEBITS) != 0);
341 win_attr.cursor = X11DRV_MOUSE_XCursor;
343 ((X11DRV_WND_DATA *) wndPtr->pDriverData)->hWMIconBitmap = 0;
344 ((X11DRV_WND_DATA *) wndPtr->pDriverData)->hWMIconMask = 0;
345 ((X11DRV_WND_DATA *) wndPtr->pDriverData)->bit_gravity = win_attr.bit_gravity;
347 /* Zero-size X11 window hack. X doesn't like them, and will crash */
348 /* with a BadValue unless we do something ugly like this. */
349 /* Zero size window won't be mapped */
350 if (cs->cx <= 0) cs->cx = 1;
351 if (cs->cy <= 0) cs->cy = 1;
354 ((X11DRV_WND_DATA *) wndPtr->pDriverData)->window =
355 TSXCreateWindow( display, X11DRV_GetXRootWindow(),
356 cs->x, cs->y, cs->cx, cs->cy,
357 0, CopyFromParent,
358 InputOutput, CopyFromParent,
359 CWEventMask | CWOverrideRedirect |
360 CWColormap | CWCursor | CWSaveUnder |
361 CWBackingStore | CWBitGravity,
362 &win_attr );
364 if(!(wGroupLeader = X11DRV_WND_GetXWindow(wndPtr)))
365 return FALSE;
367 /* If we are the systray, we need to be managed to be noticed by KWM */
369 if (wndPtr->dwExStyle & WS_EX_TRAYWINDOW)
370 X11DRV_WND_DockWindow(wndPtr);
372 if (wndPtr->dwExStyle & WS_EX_MANAGED)
374 XClassHint *class_hints = TSXAllocClassHint();
375 XSizeHints* size_hints = TSXAllocSizeHints();
377 if (class_hints)
379 class_hints->res_name = "wineManaged";
380 class_hints->res_class = "Wine";
381 TSXSetClassHint( display, ((X11DRV_WND_DATA *) wndPtr->pDriverData)->window, class_hints );
382 TSXFree (class_hints);
385 if (size_hints)
387 size_hints->win_gravity = StaticGravity;
388 size_hints->x = cs->x;
389 size_hints->y = cs->y;
390 size_hints->flags = PWinGravity|PPosition;
392 if (HAS_DLGFRAME(cs->style,cs->dwExStyle))
394 size_hints->min_width = size_hints->max_width = cs->cx;
395 size_hints->min_height = size_hints->max_height = cs->cy;
396 size_hints->flags |= PMinSize | PMaxSize;
399 TSXSetWMSizeHints( display, X11DRV_WND_GetXWindow(wndPtr),
400 size_hints, XA_WM_NORMAL_HINTS );
401 TSXFree(size_hints);
405 if (cs->hwndParent) /* Get window owner */
407 Window w;
408 WND *tmpWnd = WIN_FindWndPtr(cs->hwndParent);
410 w = X11DRV_WND_FindXWindow( tmpWnd );
411 if (w != None)
413 TSXSetTransientForHint( display, X11DRV_WND_GetXWindow(wndPtr), w );
414 wGroupLeader = w;
416 WIN_ReleaseWndPtr(tmpWnd);
419 if ((wm_hints = TSXAllocWMHints()))
421 wm_hints->flags = InputHint | StateHint | WindowGroupHint;
422 wm_hints->input = True;
424 if (wndPtr->dwExStyle & WS_EX_MANAGED)
426 X11DRV_WND_IconChanged(wndPtr);
427 X11DRV_WND_SetIconHints(wndPtr, wm_hints);
429 wm_hints->initial_state = (wndPtr->dwStyle & WS_MINIMIZE)
430 ? IconicState : NormalState;
432 else
433 wm_hints->initial_state = NormalState;
434 wm_hints->window_group = wGroupLeader;
436 TSXSetWMHints( display, X11DRV_WND_GetXWindow(wndPtr), wm_hints );
437 TSXFree(wm_hints);
439 X11DRV_WND_RegisterWindow( wndPtr );
441 return TRUE;
444 /***********************************************************************
445 * X11DRV_WND_DestroyWindow
447 BOOL X11DRV_WND_DestroyWindow(WND *wndPtr)
449 Window w;
450 if ((w = X11DRV_WND_GetXWindow(wndPtr)))
452 XEvent xe;
453 TSXDeleteContext( display, w, winContext );
454 TSXDestroyWindow( display, w );
455 while( TSXCheckWindowEvent(display, w, NoEventMask, &xe) );
457 ((X11DRV_WND_DATA *) wndPtr->pDriverData)->window = None;
458 if( ((X11DRV_WND_DATA *) wndPtr->pDriverData)->hWMIconBitmap )
460 DeleteObject( ((X11DRV_WND_DATA *) wndPtr->pDriverData)->hWMIconBitmap );
461 ((X11DRV_WND_DATA *) wndPtr->pDriverData)->hWMIconBitmap = 0;
463 if( ((X11DRV_WND_DATA *) wndPtr->pDriverData)->hWMIconMask )
465 DeleteObject( ((X11DRV_WND_DATA *) wndPtr->pDriverData)->hWMIconMask);
466 ((X11DRV_WND_DATA *) wndPtr->pDriverData)->hWMIconMask= 0;
470 return TRUE;
473 /*****************************************************************
474 * X11DRV_WND_SetParent
476 WND *X11DRV_WND_SetParent(WND *wndPtr, WND *pWndParent)
478 WND *pDesktop = WIN_GetDesktop();
480 if( wndPtr && pWndParent && (wndPtr != pDesktop) )
482 WND* pWndPrev = wndPtr->parent;
484 if( pWndParent != pWndPrev )
486 if ( X11DRV_WND_GetXWindow(wndPtr) )
488 /* Toplevel window needs to be reparented. Used by Tk 8.0 */
490 TSXDestroyWindow( display, X11DRV_WND_GetXWindow(wndPtr) );
491 ((X11DRV_WND_DATA *) wndPtr->pDriverData)->window = None;
494 WIN_UnlinkWindow(wndPtr->hwndSelf);
495 wndPtr->parent = pWndParent;
497 /* Create an X counterpart for reparented top-level windows
498 * when not in the desktop mode. */
500 if( pWndParent == pDesktop )
502 if( X11DRV_GetXRootWindow() == DefaultRootWindow(display) )
504 CREATESTRUCTA cs;
505 cs.lpCreateParams = NULL;
506 cs.hInstance = 0; /* not used in following call */
507 cs.hMenu = 0; /* not used in following call */
508 cs.hwndParent = pWndParent->hwndSelf;
509 cs.cy = wndPtr->rectWindow.bottom - wndPtr->rectWindow.top;
510 if (!cs.cy)
511 cs.cy = 1;
512 cs.cx = wndPtr->rectWindow.right - wndPtr->rectWindow.left;
513 if (!cs.cx)
514 cs.cx = 1;
515 cs.y = wndPtr->rectWindow.top;
516 cs.x = wndPtr->rectWindow.left;
517 cs.style = wndPtr->dwStyle;
518 cs.lpszName = 0; /* not used in following call */
519 cs.lpszClass = 0; /*not used in following call */
520 cs.dwExStyle = wndPtr->dwExStyle;
521 X11DRV_WND_CreateWindow(wndPtr, &cs, FALSE);
524 else /* a child window */
526 if( !( wndPtr->dwStyle & WS_CHILD ) )
528 if( wndPtr->wIDmenu != 0)
530 DestroyMenu( (HMENU) wndPtr->wIDmenu );
531 wndPtr->wIDmenu = 0;
535 WIN_LinkWindow(wndPtr->hwndSelf, HWND_TOP);
537 WIN_ReleaseDesktop();
538 return pWndPrev;
539 } /* failure */
540 WIN_ReleaseDesktop();
541 return 0;
544 /***********************************************************************
545 * X11DRV_WND_ForceWindowRaise
547 * Raise a window on top of the X stacking order, while preserving
548 * the correct Windows Z order.
550 void X11DRV_WND_ForceWindowRaise(WND *wndPtr)
552 XWindowChanges winChanges;
553 WND *wndPrev,*pDesktop = WIN_GetDesktop();
555 if (X11DRV_WND_IsZeroSizeWnd(wndPtr))
557 WIN_ReleaseDesktop();
558 return;
561 if( !wndPtr || !X11DRV_WND_GetXWindow(wndPtr) || (wndPtr->dwExStyle & WS_EX_MANAGED) )
563 WIN_ReleaseDesktop();
564 return;
567 /* Raise all windows up to wndPtr according to their Z order.
568 * (it would be easier with sibling-related Below but it doesn't
569 * work very well with SGI mwm for instance)
571 winChanges.stack_mode = Above;
572 while (wndPtr)
574 if ( !X11DRV_WND_IsZeroSizeWnd(wndPtr) && X11DRV_WND_GetXWindow(wndPtr) )
575 TSXReconfigureWMWindow( display, X11DRV_WND_GetXWindow(wndPtr), 0,
576 CWStackMode, &winChanges );
578 wndPrev = pDesktop->child;
579 if (wndPrev == wndPtr) break;
580 while (wndPrev && (wndPrev->next != wndPtr)) wndPrev = wndPrev->next;
582 wndPtr = wndPrev;
584 WIN_ReleaseDesktop();
587 /***********************************************************************
588 * X11DRV_WND_FindDesktopXWindow [Internal]
590 * Find the actual X window which needs be restacked.
591 * Used by X11DRV_WND_SetWindowPos().
593 static Window X11DRV_WND_FindDesktopXWindow( WND *wndPtr )
595 if (!(wndPtr->dwExStyle & WS_EX_MANAGED))
596 return X11DRV_WND_GetXWindow(wndPtr);
597 else
599 Window window, root, parent, *children;
600 int nchildren;
601 window = X11DRV_WND_GetXWindow(wndPtr);
602 for (;;)
604 TSXQueryTree( display, window, &root, &parent,
605 &children, &nchildren );
606 TSXFree( children );
607 if (parent == root)
608 return window;
609 window = parent;
614 /***********************************************************************
615 * WINPOS_SetXWindowPos
617 * SetWindowPos() for an X window. Used by the real SetWindowPos().
619 void X11DRV_WND_SetWindowPos(WND *wndPtr, const WINDOWPOS *winpos, BOOL bChangePos)
621 XWindowChanges winChanges;
622 int changeMask = 0;
623 BOOL isZeroSizeWnd = FALSE;
624 BOOL forceMapWindow = FALSE;
625 WND *winposPtr = WIN_FindWndPtr( winpos->hwnd );
626 if ( !winposPtr ) return;
628 /* find out if after this function we will end out with a zero-size window */
629 if (X11DRV_WND_IsZeroSizeWnd(winposPtr))
631 /* if current size is 0, and no resizing */
632 if (winpos->flags & SWP_NOSIZE)
633 isZeroSizeWnd = TRUE;
634 else if ((winpos->cx > 0) && (winpos->cy > 0))
636 /* if this function is setting a new size > 0 for the window, we
637 should map the window if WS_VISIBLE is set */
638 if ((winposPtr->dwStyle & WS_VISIBLE) && !(winpos->flags & SWP_HIDEWINDOW))
639 forceMapWindow = TRUE;
642 /* if resizing to 0 */
643 if ( !(winpos->flags & SWP_NOSIZE) && ((winpos->cx <= 0) || (winpos->cy <= 0)) )
644 isZeroSizeWnd = TRUE;
646 if(!wndPtr->hwndSelf) wndPtr = NULL; /* FIXME: WND destroyed, shouldn't happen!!! */
648 if (!(winpos->flags & SWP_SHOWWINDOW) && (winpos->flags & SWP_HIDEWINDOW))
650 if(X11DRV_WND_GetXWindow(wndPtr))
651 TSXUnmapWindow( display, X11DRV_WND_GetXWindow(wndPtr) );
654 if(bChangePos)
656 if ( !(winpos->flags & SWP_NOSIZE))
658 winChanges.width = (winpos->cx > 0 ) ? winpos->cx : 1;
659 winChanges.height = (winpos->cy > 0 ) ? winpos->cy : 1;
660 changeMask |= CWWidth | CWHeight;
662 /* Tweak dialog window size hints */
664 if ((winposPtr->dwExStyle & WS_EX_MANAGED) &&
665 HAS_DLGFRAME(winposPtr->dwStyle,winposPtr->dwExStyle))
667 XSizeHints *size_hints = TSXAllocSizeHints();
669 if (size_hints)
671 long supplied_return;
673 TSXGetWMSizeHints( display, X11DRV_WND_GetXWindow(winposPtr), size_hints,
674 &supplied_return, XA_WM_NORMAL_HINTS);
675 size_hints->min_width = size_hints->max_width = winpos->cx;
676 size_hints->min_height = size_hints->max_height = winpos->cy;
677 TSXSetWMSizeHints( display, X11DRV_WND_GetXWindow(winposPtr), size_hints,
678 XA_WM_NORMAL_HINTS );
679 TSXFree(size_hints);
683 if (!(winpos->flags & SWP_NOMOVE))
685 winChanges.x = winpos->x;
686 winChanges.y = winpos->y;
687 changeMask |= CWX | CWY;
689 if (!(winpos->flags & SWP_NOZORDER) && !isZeroSizeWnd)
691 winChanges.stack_mode = Below;
692 changeMask |= CWStackMode;
694 if (winpos->hwndInsertAfter == HWND_TOP) winChanges.stack_mode = Above;
695 else if (winpos->hwndInsertAfter != HWND_BOTTOM)
697 WND* insertPtr = WIN_FindWndPtr( winpos->hwndInsertAfter );
698 Window stack[2];
700 /* If the window where we should do the insert is zero-sized (not mapped)
701 don't used this window since it will possibly crash the X server,
702 use the "non zero-sized" window above */
703 if (X11DRV_WND_IsZeroSizeWnd(insertPtr))
705 /* find the window on top of the zero sized window */
706 WND *pDesktop = WIN_GetDesktop();
707 WND *wndPrev = pDesktop->child;
708 WND *wndZeroSized = insertPtr;
710 while (1)
712 if (wndPrev == wndZeroSized)
713 break; /* zero-sized window is on top */
715 while (wndPrev && (wndPrev->next != wndZeroSized))
716 wndPrev = wndPrev->next;
718 /* check if the window found is not zero-sized */
719 if (X11DRV_WND_IsZeroSizeWnd(wndPrev))
721 wndZeroSized = wndPrev; /* restart the search */
722 wndPrev = pDesktop->child;
724 else
725 break; /* "above" window is found */
727 WIN_ReleaseDesktop();
729 if (wndPrev == wndZeroSized)
731 /* the zero-sized window is on top */
732 /* so set the window on top */
733 winChanges.stack_mode = Above;
735 else
737 stack[0] = X11DRV_WND_FindDesktopXWindow( wndPrev );
738 stack[1] = X11DRV_WND_FindDesktopXWindow( winposPtr );
740 TSXRestackWindows(display, stack, 2);
741 changeMask &= ~CWStackMode;
744 else /* Normal behavior, windows are not zero-sized */
746 stack[0] = X11DRV_WND_FindDesktopXWindow( insertPtr );
747 stack[1] = X11DRV_WND_FindDesktopXWindow( winposPtr );
749 TSXRestackWindows(display, stack, 2);
750 changeMask &= ~CWStackMode;
753 WIN_ReleaseWndPtr(insertPtr);
756 if (changeMask && X11DRV_WND_GetXWindow(winposPtr))
758 TSXReconfigureWMWindow( display, X11DRV_WND_GetXWindow(winposPtr), 0, changeMask, &winChanges );
759 if( winposPtr->clsStyle & (CS_VREDRAW | CS_HREDRAW) )
760 X11DRV_WND_SetHostAttr( winposPtr, HAK_BITGRAVITY, BGForget );
764 /* don't map the window if it's a zero size window */
765 if ( ((winpos->flags & SWP_SHOWWINDOW) && !isZeroSizeWnd) || forceMapWindow )
767 if(X11DRV_WND_GetXWindow(wndPtr))
768 TSXMapWindow( display, X11DRV_WND_GetXWindow(wndPtr) );
770 WIN_ReleaseWndPtr(winposPtr);
773 /*****************************************************************
774 * X11DRV_WND_SetText
776 void X11DRV_WND_SetText(WND *wndPtr, LPCWSTR text)
778 UINT count;
779 char *buffer;
780 static UINT text_cp = (UINT)-1;
781 Window win;
783 if (!(win = X11DRV_WND_GetXWindow(wndPtr))) return;
785 if(text_cp == (UINT)-1)
787 text_cp = PROFILE_GetWineIniInt("x11drv", "TextCP", CP_ACP);
788 TRACE("text_cp = %u\n", text_cp);
791 /* allocate new buffer for window text */
792 count = WideCharToMultiByte(text_cp, 0, text, -1, NULL, 0, NULL, NULL);
793 if (!(buffer = HeapAlloc( GetProcessHeap(), 0, count * sizeof(WCHAR) )))
795 ERR("Not enough memory for window text\n");
796 return;
798 WideCharToMultiByte(text_cp, 0, text, -1, buffer, count, NULL, NULL);
800 TSXStoreName( display, win, buffer );
801 TSXSetIconName( display, win, buffer );
802 HeapFree( GetProcessHeap(), 0, buffer );
805 /*****************************************************************
806 * X11DRV_WND_SetFocus
808 * Set the X focus.
809 * Explicit colormap management seems to work only with OLVWM.
811 void X11DRV_WND_SetFocus(WND *wndPtr)
813 HWND hwnd = wndPtr->hwndSelf;
814 XWindowAttributes win_attr;
815 Window win;
816 WND *w = wndPtr;
818 if (X11DRV_WND_IsZeroSizeWnd(wndPtr))
819 return;
821 /* Only mess with the X focus if there's */
822 /* no desktop window and if the window is not managed by the WM. */
823 if ((X11DRV_GetXRootWindow() != DefaultRootWindow(display))) return;
824 while (w && !((X11DRV_WND_DATA *) w->pDriverData)->window)
825 w = w->parent;
826 if (!w) w = wndPtr;
827 if (w->dwExStyle & WS_EX_MANAGED) return;
829 if (!hwnd) /* If setting the focus to 0, uninstall the colormap */
831 if (X11DRV_PALETTE_PaletteFlags & X11DRV_PALETTE_PRIVATE)
832 TSXUninstallColormap( display, X11DRV_PALETTE_PaletteXColormap );
833 return;
836 /* Set X focus and install colormap */
838 if (!(win = X11DRV_WND_FindXWindow(wndPtr))) return;
839 if (!TSXGetWindowAttributes( display, win, &win_attr ) ||
840 (win_attr.map_state != IsViewable))
841 return; /* If window is not viewable, don't change anything */
843 TSXSetInputFocus( display, win, RevertToParent, CurrentTime );
844 if (X11DRV_PALETTE_PaletteFlags & X11DRV_PALETTE_PRIVATE)
845 TSXInstallColormap( display, X11DRV_PALETTE_PaletteXColormap );
847 EVENT_Synchronize();
850 /*****************************************************************
851 * X11DRV_WND_PreSizeMove
853 void X11DRV_WND_PreSizeMove(WND *wndPtr)
855 /* Grab the server only when moving top-level windows without desktop */
856 if (!(wndPtr->dwStyle & WS_CHILD) && (X11DRV_GetXRootWindow() == DefaultRootWindow(display)))
857 TSXGrabServer( display );
860 /*****************************************************************
861 * X11DRV_WND_PostSizeMove
863 void X11DRV_WND_PostSizeMove(WND *wndPtr)
865 if (!(wndPtr->dwStyle & WS_CHILD) &&
866 (X11DRV_GetXRootWindow() == DefaultRootWindow(display)))
867 TSXUngrabServer( display );
870 /*****************************************************************
871 * X11DRV_WND_SurfaceCopy
873 * Copies rect to (rect.left + dx, rect.top + dy).
875 void X11DRV_WND_SurfaceCopy(WND* wndPtr, HDC hdc, INT dx, INT dy,
876 const RECT *rect, BOOL bUpdate)
878 X11DRV_PDEVICE *physDev;
879 POINT dst, src;
880 DC *dcPtr = DC_GetDCPtr( hdc );
882 if (!dcPtr) return;
883 physDev = (X11DRV_PDEVICE *)dcPtr->physDev;
884 dst.x = (src.x = dcPtr->DCOrgX + rect->left) + dx;
885 dst.y = (src.y = dcPtr->DCOrgY + rect->top) + dy;
887 if (bUpdate) /* handles non-Wine windows hanging over the copied area */
888 TSXSetGraphicsExposures( display, physDev->gc, True );
889 TSXSetFunction( display, physDev->gc, GXcopy );
890 TSXCopyArea( display, physDev->drawable, physDev->drawable,
891 physDev->gc, src.x, src.y,
892 rect->right - rect->left,
893 rect->bottom - rect->top,
894 dst.x, dst.y );
895 if (bUpdate)
896 TSXSetGraphicsExposures( display, physDev->gc, False );
897 GDI_ReleaseObj( hdc );
899 if (bUpdate) /* Make sure exposure events have been processed */
900 EVENT_Synchronize();
903 /***********************************************************************
904 * X11DRV_WND_SetDrawable
906 * Set the drawable, origin and dimensions for the DC associated to
907 * a given window.
909 void X11DRV_WND_SetDrawable(WND *wndPtr, HDC hdc, WORD flags, BOOL bSetClipOrigin)
911 DC *dc = DC_GetDCPtr( hdc );
912 X11DRV_PDEVICE *physDev;
913 INT dcOrgXCopy = 0, dcOrgYCopy = 0;
914 BOOL offsetClipRgn = FALSE;
916 if (!dc) return;
917 physDev = (X11DRV_PDEVICE *)dc->physDev;
918 if (!wndPtr) /* Get a DC for the whole screen */
920 dc->DCOrgX = 0;
921 dc->DCOrgY = 0;
922 physDev->drawable = X11DRV_GetXRootWindow();
923 TSXSetSubwindowMode( display, physDev->gc, IncludeInferiors );
925 else
928 * This function change the coordinate system (DCOrgX,DCOrgY)
929 * values. When it moves the origin, other data like the current clipping
930 * region will not be moved to that new origin. In the case of DCs that are class
931 * or window DCs that clipping region might be a valid value from a previous use
932 * of the DC and changing the origin of the DC without moving the clip region
933 * results in a clip region that is not placed properly in the DC.
934 * This code will save the dc origin, let the SetDrawable
935 * modify the origin and reset the clipping. When the clipping is set,
936 * it is moved according to the new DC origin.
938 if ( (wndPtr->clsStyle & (CS_OWNDC | CS_CLASSDC)) && (dc->hClipRgn > 0))
940 dcOrgXCopy = dc->DCOrgX;
941 dcOrgYCopy = dc->DCOrgY;
942 offsetClipRgn = TRUE;
945 if (flags & DCX_WINDOW)
947 dc->DCOrgX = wndPtr->rectWindow.left;
948 dc->DCOrgY = wndPtr->rectWindow.top;
950 else
952 dc->DCOrgX = wndPtr->rectClient.left;
953 dc->DCOrgY = wndPtr->rectClient.top;
955 while (!X11DRV_WND_GetXWindow(wndPtr))
957 wndPtr = wndPtr->parent;
958 dc->DCOrgX += wndPtr->rectClient.left;
959 dc->DCOrgY += wndPtr->rectClient.top;
961 dc->DCOrgX -= wndPtr->rectWindow.left;
962 dc->DCOrgY -= wndPtr->rectWindow.top;
964 /* reset the clip region, according to the new origin */
965 if ( offsetClipRgn )
967 OffsetRgn(dc->hClipRgn, dc->DCOrgX - dcOrgXCopy,dc->DCOrgY - dcOrgYCopy);
970 physDev->drawable = X11DRV_WND_GetXWindow(wndPtr);
972 #if 0
973 /* This is needed when we reuse a cached DC because
974 * SetDCState() called by ReleaseDC() screws up DC
975 * origins for child windows.
978 if( bSetClipOrigin )
979 TSXSetClipOrigin( display, physDev->gc, dc->DCOrgX, dc->DCOrgY );
980 #endif
982 GDI_ReleaseObj( hdc );
985 /***********************************************************************
986 * X11DRV_SetWMHint
988 static BOOL X11DRV_SetWMHint(Display* display, WND* wndPtr, int hint, int val)
990 XWMHints* wm_hints = TSXGetWMHints( display, X11DRV_WND_GetXWindow(wndPtr) );
991 if (!wm_hints) wm_hints = TSXAllocWMHints();
992 if (wm_hints)
994 wm_hints->flags = hint;
995 switch( hint )
997 case InputHint:
998 wm_hints->input = val;
999 break;
1001 case StateHint:
1002 wm_hints->initial_state = val;
1003 break;
1005 case IconPixmapHint:
1006 wm_hints->icon_pixmap = (Pixmap)val;
1007 break;
1009 case IconWindowHint:
1010 wm_hints->icon_window = (Window)val;
1011 break;
1014 TSXSetWMHints( display, X11DRV_WND_GetXWindow(wndPtr), wm_hints );
1015 TSXFree(wm_hints);
1016 return TRUE;
1018 return FALSE;
1022 /***********************************************************************
1023 * X11DRV_WND_SetHostAttr
1025 * This function returns TRUE if the attribute is supported and the
1026 * action was successful. Otherwise it should return FALSE and Wine will try
1027 * to get by without the functionality provided by the host window system.
1029 BOOL X11DRV_WND_SetHostAttr(WND* wnd, INT ha, INT value)
1031 Window w;
1033 if( (w = X11DRV_WND_GetXWindow(wnd)) )
1035 XSetWindowAttributes win_attr;
1037 switch( ha )
1039 case HAK_ICONICSTATE: /* called when a window is minimized/restored */
1041 /* don't do anything if it'a zero size window */
1042 if (X11DRV_WND_IsZeroSizeWnd(wnd))
1043 return TRUE;
1045 if( (wnd->dwExStyle & WS_EX_MANAGED) )
1047 if( value )
1049 if( wnd->dwStyle & WS_VISIBLE )
1051 XClientMessageEvent ev;
1053 /* FIXME: set proper icon */
1055 ev.type = ClientMessage;
1056 ev.display = display;
1057 ev.message_type = wmChangeState;
1058 ev.format = 32;
1059 ev.data.l[0] = IconicState;
1060 ev.window = w;
1062 if( TSXSendEvent (display,
1063 RootWindow( display, XScreenNumberOfScreen(X11DRV_GetXScreen()) ),
1064 True, (SubstructureRedirectMask | SubstructureNotifyMask), (XEvent*)&ev))
1066 XEvent xe;
1067 TSXFlush (display);
1068 while( !TSXCheckTypedWindowEvent( display, w, UnmapNotify, &xe) );
1070 else
1071 break;
1073 else
1074 X11DRV_SetWMHint( display, wnd, StateHint, IconicState );
1076 else
1078 if( !(wnd->flags & WS_VISIBLE) )
1079 X11DRV_SetWMHint( display, wnd, StateHint, NormalState );
1080 else
1082 XEvent xe;
1083 TSXMapWindow(display, w );
1084 while( !TSXCheckTypedWindowEvent( display, w, MapNotify, &xe) );
1087 return TRUE;
1089 break;
1091 case HAK_BITGRAVITY: /* called when a window is resized */
1093 if( ((X11DRV_WND_DATA *) wnd->pDriverData)->bit_gravity != value )
1095 win_attr.bit_gravity = value;
1096 ((X11DRV_WND_DATA *) wnd->pDriverData)->bit_gravity = value;
1097 TSXChangeWindowAttributes( display, w, CWBitGravity, &win_attr );
1099 return TRUE;
1101 case HAK_ICONS: /* called when the icons change */
1102 if ( (wnd->dwExStyle & WS_EX_MANAGED) )
1103 X11DRV_WND_UpdateIconHints(wnd);
1104 return TRUE;
1106 case HAK_ACCEPTFOCUS: /* called when a window is disabled/enabled */
1108 if( (wnd->dwExStyle & WS_EX_MANAGED) )
1109 return X11DRV_SetWMHint( display, wnd, InputHint, value );
1112 return FALSE;
1115 /***********************************************************************
1116 * X11DRV_WND_IsSelfClipping
1118 BOOL X11DRV_WND_IsSelfClipping(WND *wndPtr)
1120 return X11DRV_WND_GetXWindow(wndPtr) != None;
1123 /***********************************************************************
1124 * X11DRV_WND_DockWindow
1126 * Set the X Property of the window that tells the windowmanager we really
1127 * want to be in the systray
1129 * KDE: set "KWM_DOCKWINDOW", type "KWM_DOCKWINDOW" to 1 before a window is
1130 * mapped.
1132 * all others: to be added ;)
1134 void X11DRV_WND_DockWindow(WND *wndPtr)
1136 int data = 1;
1137 Window win = X11DRV_WND_GetXWindow(wndPtr);
1138 if (kwmDockWindow != None) {
1139 TSXChangeProperty(
1140 display,win,kwmDockWindow,kwmDockWindow,32,PropModeReplace,(char*)&data,1
1143 if (_kde_net_wm_system_tray_window_for != None) {
1144 TSXChangeProperty(
1145 display,
1146 win,
1147 _kde_net_wm_system_tray_window_for,
1148 XA_WINDOW,
1150 PropModeReplace,
1151 (char*)&win,
1155 if (_net_kde_system_tray_window_for != None) {
1156 TSXChangeProperty(
1157 display,
1158 win,
1159 _net_kde_system_tray_window_for,
1160 XA_WINDOW,
1162 PropModeReplace,
1163 (char*)&win,
1171 /***********************************************************************
1172 * X11DRV_WND_SetWindowRgn
1174 * Assign specified region to window (for non-rectangular windows)
1176 void X11DRV_WND_SetWindowRgn(WND *wndPtr, HRGN hrgnWnd)
1178 #ifdef HAVE_LIBXSHAPE
1179 Window win = X11DRV_WND_GetXWindow(wndPtr);
1181 if (!win) return;
1183 if (!hrgnWnd)
1185 TSXShapeCombineMask( display, win, ShapeBounding, 0, 0, None, ShapeSet );
1187 else
1189 XRectangle *aXRect;
1190 DWORD size;
1191 DWORD dwBufferSize = GetRegionData(hrgnWnd, 0, NULL);
1192 PRGNDATA pRegionData = HeapAlloc(GetProcessHeap(), 0, dwBufferSize);
1193 if (!pRegionData) return;
1195 GetRegionData(hrgnWnd, dwBufferSize, pRegionData);
1196 size = pRegionData->rdh.nCount;
1197 /* convert region's "Windows rectangles" to XRectangles */
1198 aXRect = HeapAlloc(GetProcessHeap(), 0, size * sizeof(*aXRect) );
1199 if (aXRect)
1201 XRectangle* pCurrRect = aXRect;
1202 RECT *pRect = (RECT*) pRegionData->Buffer;
1203 for (; pRect < ((RECT*) pRegionData->Buffer) + size ; ++pRect, ++pCurrRect)
1205 pCurrRect->x = pRect->left;
1206 pCurrRect->y = pRect->top;
1207 pCurrRect->height = pRect->bottom - pRect->top;
1208 pCurrRect->width = pRect->right - pRect->left;
1210 TRACE("Rectangle %04d of %04ld data: X=%04d, Y=%04d, Height=%04d, Width=%04d.\n",
1211 pRect - (RECT*) pRegionData->Buffer,
1212 size,
1213 pCurrRect->x,
1214 pCurrRect->y,
1215 pCurrRect->height,
1216 pCurrRect->width);
1219 /* shape = non-rectangular windows (X11/extensions) */
1220 TSXShapeCombineRectangles( display, win, ShapeBounding,
1221 0, 0, aXRect,
1222 pCurrRect - aXRect, ShapeSet, YXBanded );
1223 HeapFree(GetProcessHeap(), 0, aXRect );
1225 HeapFree(GetProcessHeap(), 0, pRegionData);
1227 #endif /* HAVE_LIBXSHAPE */