Set the class hints for managed windows.
[wine/multimedia.git] / windows / x11drv / wnd.c
blobcf5ae7b4bda7460335b6859c04a451825e5a72fe
1 /*
2 * X11 windows driver
4 * Copyright 1993, 1994, 1995, 1996 Alexandre Julliard
5 * 1993 David Metcalfe
6 * 1995, 1996 Alex Korobka
7 */
9 #include "config.h"
11 #ifndef X_DISPLAY_MISSING
13 #include <X11/Xatom.h>
14 #include "ts_xlib.h"
15 #include "ts_xutil.h"
17 #include <stdlib.h>
18 #include <string.h>
19 #include "color.h"
20 #include "display.h"
21 #include "dce.h"
22 #include "options.h"
23 #include "message.h"
24 #include "win.h"
25 #include "windows.h"
26 #include "x11drv.h"
28 /**********************************************************************/
30 extern Cursor DISPLAY_XCursor; /* Current X cursor */
32 /**********************************************************************/
34 /* X context to associate a hwnd to an X window */
35 XContext winContext = 0;
37 Atom wmProtocols = None;
38 Atom wmDeleteWindow = None;
39 Atom dndProtocol = None;
40 Atom dndSelection = None;
42 /***********************************************************************
43 * X11DRV_WND_GetXWindow
45 * Return the X window associated to a window.
47 Window X11DRV_WND_GetXWindow(HWND32 hwnd)
49 WND *wndPtr = WIN_FindWndPtr( hwnd );
50 while (wndPtr && !wndPtr->window) wndPtr = wndPtr->parent;
51 return wndPtr ? wndPtr->window : 0;
54 /***********************************************************************
55 * X11DRV_WND_RegisterWindow
57 * Associate an X window to a HWND.
59 static void X11DRV_WND_RegisterWindow(WND *pWnd)
61 TSXSetWMProtocols( display, pWnd->window, &wmDeleteWindow, 1 );
63 if (!winContext) winContext = TSXUniqueContext();
64 TSXSaveContext( display, pWnd->window, winContext, (char *)pWnd );
67 /**********************************************************************
68 * X11DRV_WND_CreateDesktopWindow
70 BOOL32 X11DRV_WND_CreateDesktopWindow(WND *wndPtr, CLASS *classPtr, BOOL32 bUnicode)
72 if (wmProtocols == None)
73 wmProtocols = TSXInternAtom( display, "WM_PROTOCOLS", True );
74 if (wmDeleteWindow == None)
75 wmDeleteWindow = TSXInternAtom( display, "WM_DELETE_WINDOW", True );
76 if( dndProtocol == None )
77 dndProtocol = TSXInternAtom( display, "DndProtocol" , False );
78 if( dndSelection == None )
79 dndSelection = TSXInternAtom( display, "DndSelection" , False );
81 wndPtr->window = rootWindow;
82 X11DRV_WND_RegisterWindow( wndPtr );
84 return TRUE;
87 /**********************************************************************
88 * X11DRV_WND_CreateWindow
90 BOOL32 X11DRV_WND_CreateWindow(WND *wndPtr, CLASS *classPtr, CREATESTRUCT32A *cs, BOOL32 bUnicode)
92 /* Create the X window (only for top-level windows, and then only */
93 /* when there's no desktop window) */
95 if (!(cs->style & WS_CHILD) && (rootWindow == DefaultRootWindow(display)))
97 XSetWindowAttributes win_attr;
99 if (Options.managed && ((cs->style & (WS_DLGFRAME | WS_THICKFRAME)) ||
100 (cs->dwExStyle & WS_EX_DLGMODALFRAME)))
102 win_attr.event_mask = ExposureMask | KeyPressMask |
103 KeyReleaseMask | PointerMotionMask |
104 ButtonPressMask | ButtonReleaseMask |
105 FocusChangeMask | StructureNotifyMask;
106 win_attr.override_redirect = FALSE;
107 wndPtr->flags |= WIN_MANAGED;
109 else
111 win_attr.event_mask = ExposureMask | KeyPressMask |
112 KeyReleaseMask | PointerMotionMask |
113 ButtonPressMask | ButtonReleaseMask |
114 FocusChangeMask;
115 win_attr.override_redirect = TRUE;
117 win_attr.colormap = COLOR_GetColormap();
118 win_attr.backing_store = Options.backingstore ? WhenMapped : NotUseful;
119 win_attr.save_under = ((classPtr->style & CS_SAVEBITS) != 0);
120 win_attr.cursor = DISPLAY_XCursor;
121 wndPtr->window = TSXCreateWindow( display, rootWindow, cs->x, cs->y,
122 cs->cx, cs->cy, 0, CopyFromParent,
123 InputOutput, CopyFromParent,
124 CWEventMask | CWOverrideRedirect |
125 CWColormap | CWCursor | CWSaveUnder |
126 CWBackingStore, &win_attr );
128 if(!wndPtr->window)
129 return FALSE;
131 if (wndPtr->flags & WIN_MANAGED) {
132 XClassHint *class_hints = TSXAllocClassHint();
134 if (class_hints) {
135 class_hints->res_name = "wineManaged";
136 class_hints->res_class = "Wine";
137 TSXSetClassHint( display, wndPtr->window, class_hints );
138 TSXFree (class_hints);
141 if (cs->dwExStyle & WS_EX_DLGMODALFRAME) {
142 XSizeHints* size_hints = TSXAllocSizeHints();
144 if (size_hints) {
145 size_hints->min_width = size_hints->max_width = cs->cx;
146 size_hints->min_height = size_hints->max_height = cs->cy;
147 size_hints->flags = (PSize | PMinSize | PMaxSize);
148 TSXSetWMSizeHints( display, wndPtr->window, size_hints,
149 XA_WM_NORMAL_HINTS );
150 TSXFree(size_hints);
155 if (cs->hwndParent) /* Get window owner */
157 Window win = X11DRV_WND_GetXWindow( cs->hwndParent );
158 if (win) TSXSetTransientForHint( display, wndPtr->window, win );
160 X11DRV_WND_RegisterWindow( wndPtr );
162 return TRUE;
165 /***********************************************************************
166 * X11DRV_WND_DestroyWindow
168 BOOL32 X11DRV_WND_DestroyWindow(WND *pWnd)
170 if (pWnd->window)
172 XEvent xe;
173 TSXDeleteContext( display, pWnd->window, winContext );
174 TSXDestroyWindow( display, pWnd->window );
175 while( TSXCheckWindowEvent(display, pWnd->window, NoEventMask, &xe) );
176 pWnd->window = None;
179 return TRUE;
182 /*****************************************************************
183 * X11DRV_WND_SetParent
185 WND *X11DRV_WND_SetParent(WND *wndPtr, WND *pWndParent)
187 if( wndPtr && pWndParent && (wndPtr != WIN_GetDesktop()) )
189 WND* pWndPrev = wndPtr->parent;
191 if( pWndParent != pWndPrev )
193 BOOL32 bFixupDCE = IsWindowVisible32(wndPtr->hwndSelf);
195 if ( wndPtr->window )
197 /* Toplevel window needs to be reparented. Used by Tk 8.0 */
199 TSXDestroyWindow( display, wndPtr->window );
200 wndPtr->window = None;
202 else if( bFixupDCE )
203 DCE_InvalidateDCE( wndPtr, &wndPtr->rectWindow );
205 WIN_UnlinkWindow(wndPtr->hwndSelf);
206 wndPtr->parent = pWndParent;
208 /* FIXME: Create an X counterpart for reparented top-level windows
209 * when not in the desktop mode. */
211 if ( pWndParent != WIN_GetDesktop() ) wndPtr->dwStyle |= WS_CHILD;
212 WIN_LinkWindow(wndPtr->hwndSelf, HWND_BOTTOM);
214 if( bFixupDCE )
216 DCE_InvalidateDCE( wndPtr, &wndPtr->rectWindow );
217 UpdateWindow32(wndPtr->hwndSelf);
220 return pWndPrev;
221 } /* failure */
222 return 0;
225 /***********************************************************************
226 * X11DRV_WND_ForceWindowRaise
228 * Raise a window on top of the X stacking order, while preserving
229 * the correct Windows Z order.
231 void X11DRV_WND_ForceWindowRaise(WND *pWnd)
233 XWindowChanges winChanges;
234 WND *wndPrev;
236 if( !pWnd || !pWnd->window || (pWnd->flags & WIN_MANAGED) )
237 return;
239 /* Raise all windows up to pWnd according to their Z order.
240 * (it would be easier with sibling-related Below but it doesn't
241 * work very well with SGI mwm for instance)
243 winChanges.stack_mode = Above;
244 while (pWnd)
246 if (pWnd->window) TSXReconfigureWMWindow( display, pWnd->window, 0,
247 CWStackMode, &winChanges );
248 wndPrev = WIN_GetDesktop()->child;
249 if (wndPrev == pWnd) break;
250 while (wndPrev && (wndPrev->next != pWnd)) wndPrev = wndPrev->next;
251 pWnd = wndPrev;
255 /***********************************************************************
256 * X11DRV_WND_FindDesktopXWindow [Internal]
258 * Find the actual X window which needs be restacked.
259 * Used by X11DRV_SetWindowPos().
261 static Window X11DRV_WND_FindDesktopXWindow( WND *wndPtr )
263 if (!(wndPtr->flags & WIN_MANAGED))
264 return wndPtr->window;
265 else
267 Window window, root, parent, *children;
268 int nchildren;
269 window = wndPtr->window;
270 for (;;)
272 TSXQueryTree( display, window, &root, &parent,
273 &children, &nchildren );
274 TSXFree( children );
275 if (parent == root)
276 return window;
277 window = parent;
282 /***********************************************************************
283 * WINPOS_SetXWindowPos
285 * SetWindowPos() for an X window. Used by the real SetWindowPos().
287 void X11DRV_WND_SetWindowPos(WND *wndPtr, const WINDOWPOS32 *winpos, BOOL32 bSMC_SETXPOS)
289 XWindowChanges winChanges;
290 int changeMask = 0;
291 WND *winposPtr = WIN_FindWndPtr( winpos->hwnd );
293 if (!(winpos->flags & SWP_SHOWWINDOW) && (winpos->flags & SWP_HIDEWINDOW))
295 if(wndPtr && wndPtr->window) TSXUnmapWindow( display, wndPtr->window );
298 if(bSMC_SETXPOS)
300 if ( !(winpos->flags & SWP_NOSIZE))
302 winChanges.width = winpos->cx;
303 winChanges.height = winpos->cy;
304 changeMask |= CWWidth | CWHeight;
306 /* Tweak dialog window size hints */
308 if ((winposPtr->flags & WIN_MANAGED) &&
309 (winposPtr->dwExStyle & WS_EX_DLGMODALFRAME))
311 XSizeHints *size_hints = TSXAllocSizeHints();
313 if (size_hints)
315 long supplied_return;
317 TSXGetWMSizeHints( display, winposPtr->window, size_hints,
318 &supplied_return, XA_WM_NORMAL_HINTS);
319 size_hints->min_width = size_hints->max_width = winpos->cx;
320 size_hints->min_height = size_hints->max_height = winpos->cy;
321 TSXSetWMSizeHints( display, winposPtr->window, size_hints,
322 XA_WM_NORMAL_HINTS );
323 TSXFree(size_hints);
327 if (!(winpos->flags & SWP_NOMOVE))
329 winChanges.x = winpos->x;
330 winChanges.y = winpos->y;
331 changeMask |= CWX | CWY;
333 if (!(winpos->flags & SWP_NOZORDER))
335 winChanges.stack_mode = Below;
336 changeMask |= CWStackMode;
338 if (winpos->hwndInsertAfter == HWND_TOP) winChanges.stack_mode = Above;
339 else if (winpos->hwndInsertAfter != HWND_BOTTOM)
341 WND* insertPtr = WIN_FindWndPtr( winpos->hwndInsertAfter );
342 Window stack[2];
344 stack[0] = X11DRV_WND_FindDesktopXWindow( insertPtr );
345 stack[1] = X11DRV_WND_FindDesktopXWindow( winposPtr );
347 /* for stupid window managers (i.e. all of them) */
349 TSXRestackWindows(display, stack, 2);
350 changeMask &= ~CWStackMode;
353 if (changeMask)
355 TSXReconfigureWMWindow( display, winposPtr->window, 0, changeMask, &winChanges );
359 if ( winpos->flags & SWP_SHOWWINDOW )
361 if(wndPtr && wndPtr->window) TSXMapWindow( display, wndPtr->window );
365 /*****************************************************************
366 * X11DRV_WND_SetText
368 void X11DRV_WND_SetText(WND *wndPtr, LPCSTR text)
370 if (!wndPtr->window)
371 return;
373 TSXStoreName( display, wndPtr->window, text );
374 TSXSetIconName( display, wndPtr->window, text );
377 /*****************************************************************
378 * X11DRV_WND_SetFocus
380 * Set the X focus.
381 * Explicit colormap management seems to work only with OLVWM.
383 void X11DRV_WND_SetFocus(WND *wndPtr)
385 HWND32 hwnd = wndPtr->hwndSelf;
386 XWindowAttributes win_attr;
388 /* Only mess with the X focus if there's */
389 /* no desktop window and no window manager. */
390 if ((rootWindow != DefaultRootWindow(display)) || Options.managed) return;
392 if (!hwnd) /* If setting the focus to 0, uninstall the colormap */
394 if (COLOR_GetSystemPaletteFlags() & COLOR_PRIVATE)
395 TSXUninstallColormap( display, COLOR_GetColormap() );
396 return;
399 /* Set X focus and install colormap */
401 if (!wndPtr->window) return;
403 if (!TSXGetWindowAttributes( display, wndPtr->window, &win_attr ) ||
404 (win_attr.map_state != IsViewable))
405 return; /* If window is not viewable, don't change anything */
407 TSXSetInputFocus( display,wndPtr->window, RevertToParent, CurrentTime );
408 if (COLOR_GetSystemPaletteFlags() & COLOR_PRIVATE)
409 TSXInstallColormap( display, COLOR_GetColormap() );
411 EVENT_Synchronize();
414 /*****************************************************************
415 * X11DRV_WND_PreSizeMove
417 void X11DRV_WND_PreSizeMove(WND *wndPtr)
419 if (!(wndPtr->dwStyle & WS_CHILD) && (rootWindow == DefaultRootWindow(display)))
420 TSXGrabServer( display );
423 /*****************************************************************
424 * X11DRV_WND_PostSizeMove
426 void X11DRV_WND_PostSizeMove(WND *wndPtr)
428 if (!(wndPtr->dwStyle & WS_CHILD) && (rootWindow == DefaultRootWindow(display)))
429 TSXUngrabServer( display );
432 #endif /* !defined(X_DISPLAY_MISSING) */