Removed deferred Expose events handling.
[wine.git] / windows / x11drv / wnd.c
blobb31a9d75cfb203028e6fde6648ff67c351d8e8f3
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 (cs->dwExStyle & WS_EX_DLGMODALFRAME))
134 XSizeHints* size_hints = TSXAllocSizeHints();
136 if (size_hints)
138 size_hints->min_width = size_hints->max_width = cs->cx;
139 size_hints->min_height = size_hints->max_height = cs->cy;
140 size_hints->flags = (PSize | PMinSize | PMaxSize);
141 TSXSetWMSizeHints( display, wndPtr->window, size_hints,
142 XA_WM_NORMAL_HINTS );
143 TSXFree(size_hints);
147 if (cs->hwndParent) /* Get window owner */
149 Window win = X11DRV_WND_GetXWindow( cs->hwndParent );
150 if (win) TSXSetTransientForHint( display, wndPtr->window, win );
152 X11DRV_WND_RegisterWindow( wndPtr );
154 return TRUE;
157 /***********************************************************************
158 * X11DRV_WND_DestroyWindow
160 BOOL32 X11DRV_WND_DestroyWindow(WND *pWnd)
162 if (pWnd->window)
164 XEvent xe;
165 TSXDeleteContext( display, pWnd->window, winContext );
166 TSXDestroyWindow( display, pWnd->window );
167 while( TSXCheckWindowEvent(display, pWnd->window, NoEventMask, &xe) );
168 pWnd->window = None;
171 return TRUE;
174 /*****************************************************************
175 * X11DRV_WND_SetParent
177 WND *X11DRV_WND_SetParent(WND *wndPtr, WND *pWndParent)
179 if( wndPtr && pWndParent && (wndPtr != WIN_GetDesktop()) )
181 WND* pWndPrev = wndPtr->parent;
183 if( pWndParent != pWndPrev )
185 BOOL32 bFixupDCE = IsWindowVisible32(wndPtr->hwndSelf);
187 if ( wndPtr->window )
189 /* Toplevel window needs to be reparented. Used by Tk 8.0 */
191 TSXDestroyWindow( display, wndPtr->window );
192 wndPtr->window = None;
194 else if( bFixupDCE )
195 DCE_InvalidateDCE( wndPtr, &wndPtr->rectWindow );
197 WIN_UnlinkWindow(wndPtr->hwndSelf);
198 wndPtr->parent = pWndParent;
200 /* FIXME: Create an X counterpart for reparented top-level windows
201 * when not in the desktop mode. */
203 if ( pWndParent != WIN_GetDesktop() ) wndPtr->dwStyle |= WS_CHILD;
204 WIN_LinkWindow(wndPtr->hwndSelf, HWND_BOTTOM);
206 if( bFixupDCE )
208 DCE_InvalidateDCE( wndPtr, &wndPtr->rectWindow );
209 UpdateWindow32(wndPtr->hwndSelf);
212 return pWndPrev;
213 } /* failure */
214 return 0;
217 /***********************************************************************
218 * X11DRV_WND_ForceWindowRaise
220 * Raise a window on top of the X stacking order, while preserving
221 * the correct Windows Z order.
223 void X11DRV_WND_ForceWindowRaise(WND *pWnd)
225 XWindowChanges winChanges;
226 WND *wndPrev;
228 if( !pWnd || !pWnd->window || (pWnd->flags & WIN_MANAGED) )
229 return;
231 /* Raise all windows up to pWnd according to their Z order.
232 * (it would be easier with sibling-related Below but it doesn't
233 * work very well with SGI mwm for instance)
235 winChanges.stack_mode = Above;
236 while (pWnd)
238 if (pWnd->window) TSXReconfigureWMWindow( display, pWnd->window, 0,
239 CWStackMode, &winChanges );
240 wndPrev = WIN_GetDesktop()->child;
241 if (wndPrev == pWnd) break;
242 while (wndPrev && (wndPrev->next != pWnd)) wndPrev = wndPrev->next;
243 pWnd = wndPrev;
247 /***********************************************************************
248 * X11DRV_WND_FindDesktopXWindow [Internal]
250 * Find the actual X window which needs be restacked.
251 * Used by X11DRV_SetWindowPos().
253 static Window X11DRV_WND_FindDesktopXWindow( WND *wndPtr )
255 if (!(wndPtr->flags & WIN_MANAGED))
256 return wndPtr->window;
257 else
259 Window window, root, parent, *children;
260 int nchildren;
261 window = wndPtr->window;
262 for (;;)
264 TSXQueryTree( display, window, &root, &parent,
265 &children, &nchildren );
266 TSXFree( children );
267 if (parent == root)
268 return window;
269 window = parent;
274 /***********************************************************************
275 * WINPOS_SetXWindowPos
277 * SetWindowPos() for an X window. Used by the real SetWindowPos().
279 void X11DRV_WND_SetWindowPos(WND *wndPtr, const WINDOWPOS32 *winpos, BOOL32 bSMC_SETXPOS)
281 XWindowChanges winChanges;
282 int changeMask = 0;
283 WND *winposPtr = WIN_FindWndPtr( winpos->hwnd );
285 if (!(winpos->flags & SWP_SHOWWINDOW) && (winpos->flags & SWP_HIDEWINDOW))
287 if(wndPtr && wndPtr->window) TSXUnmapWindow( display, wndPtr->window );
290 if(bSMC_SETXPOS)
292 if ( !(winpos->flags & SWP_NOSIZE))
294 winChanges.width = winpos->cx;
295 winChanges.height = winpos->cy;
296 changeMask |= CWWidth | CWHeight;
298 /* Tweak dialog window size hints */
300 if ((winposPtr->flags & WIN_MANAGED) &&
301 (winposPtr->dwExStyle & WS_EX_DLGMODALFRAME))
303 XSizeHints *size_hints = TSXAllocSizeHints();
305 if (size_hints)
307 long supplied_return;
309 TSXGetWMSizeHints( display, winposPtr->window, size_hints,
310 &supplied_return, XA_WM_NORMAL_HINTS);
311 size_hints->min_width = size_hints->max_width = winpos->cx;
312 size_hints->min_height = size_hints->max_height = winpos->cy;
313 TSXSetWMSizeHints( display, winposPtr->window, size_hints,
314 XA_WM_NORMAL_HINTS );
315 TSXFree(size_hints);
319 if (!(winpos->flags & SWP_NOMOVE))
321 winChanges.x = winpos->x;
322 winChanges.y = winpos->y;
323 changeMask |= CWX | CWY;
325 if (!(winpos->flags & SWP_NOZORDER))
327 winChanges.stack_mode = Below;
328 changeMask |= CWStackMode;
330 if (winpos->hwndInsertAfter == HWND_TOP) winChanges.stack_mode = Above;
331 else if (winpos->hwndInsertAfter != HWND_BOTTOM)
333 WND* insertPtr = WIN_FindWndPtr( winpos->hwndInsertAfter );
334 Window stack[2];
336 stack[0] = X11DRV_WND_FindDesktopXWindow( insertPtr );
337 stack[1] = X11DRV_WND_FindDesktopXWindow( winposPtr );
339 /* for stupid window managers (i.e. all of them) */
341 TSXRestackWindows(display, stack, 2);
342 changeMask &= ~CWStackMode;
345 if (changeMask)
347 TSXReconfigureWMWindow( display, winposPtr->window, 0, changeMask, &winChanges );
351 if ( winpos->flags & SWP_SHOWWINDOW )
353 if(wndPtr && wndPtr->window) TSXMapWindow( display, wndPtr->window );
357 /*****************************************************************
358 * X11DRV_WND_SetText
360 void X11DRV_WND_SetText(WND *wndPtr, LPCSTR text)
362 if (!wndPtr->window)
363 return;
365 TSXStoreName( display, wndPtr->window, text );
366 TSXSetIconName( display, wndPtr->window, text );
369 /*****************************************************************
370 * X11DRV_WND_SetFocus
372 * Set the X focus.
373 * Explicit colormap management seems to work only with OLVWM.
375 void X11DRV_WND_SetFocus(WND *wndPtr)
377 HWND32 hwnd = wndPtr->hwndSelf;
378 XWindowAttributes win_attr;
380 /* Only mess with the X focus if there's */
381 /* no desktop window and no window manager. */
382 if ((rootWindow != DefaultRootWindow(display)) || Options.managed) return;
384 if (!hwnd) /* If setting the focus to 0, uninstall the colormap */
386 if (COLOR_GetSystemPaletteFlags() & COLOR_PRIVATE)
387 TSXUninstallColormap( display, COLOR_GetColormap() );
388 return;
391 /* Set X focus and install colormap */
393 if (!wndPtr->window) return;
395 if (!TSXGetWindowAttributes( display, wndPtr->window, &win_attr ) ||
396 (win_attr.map_state != IsViewable))
397 return; /* If window is not viewable, don't change anything */
399 TSXSetInputFocus( display,wndPtr->window, RevertToParent, CurrentTime );
400 if (COLOR_GetSystemPaletteFlags() & COLOR_PRIVATE)
401 TSXInstallColormap( display, COLOR_GetColormap() );
403 EVENT_Synchronize();
406 /*****************************************************************
407 * X11DRV_WND_PreSizeMove
409 void X11DRV_WND_PreSizeMove(WND *wndPtr)
411 if (!(wndPtr->dwStyle & WS_CHILD) && (rootWindow == DefaultRootWindow(display)))
412 TSXGrabServer( display );
415 /*****************************************************************
416 * X11DRV_WND_PostSizeMove
418 void X11DRV_WND_PostSizeMove(WND *wndPtr)
420 if (!(wndPtr->dwStyle & WS_CHILD) && (rootWindow == DefaultRootWindow(display)))
421 TSXUngrabServer( display );
424 #endif /* !defined(X_DISPLAY_MISSING) */