blob: a877dec0bb5c831af8439cd28e2f25c4e1d7f2af [file] [log] [blame]
Patrik Stridvalle35d6361998-12-07 09:13:40 +00001/*
2 * X11 windows driver
3 *
4 * Copyright 1993, 1994, 1995, 1996 Alexandre Julliard
5 * 1993 David Metcalfe
6 * 1995, 1996 Alex Korobka
7 */
8
9#include "config.h"
10
11#ifndef X_DISPLAY_MISSING
12
13#include <X11/Xatom.h>
14#include "ts_xlib.h"
15#include "ts_xutil.h"
16
17#include <stdlib.h>
18#include <string.h>
19#include "color.h"
Patrik Stridvall151170c1998-12-26 12:00:43 +000020#include "debug.h"
Patrik Stridvalle35d6361998-12-07 09:13:40 +000021#include "display.h"
22#include "dce.h"
23#include "options.h"
24#include "message.h"
Patrik Stridvall151170c1998-12-26 12:00:43 +000025#include "heap.h"
Patrik Stridvalle35d6361998-12-07 09:13:40 +000026#include "win.h"
Jim Aston2e1cafa1999-03-14 16:35:05 +000027#include "windef.h"
Patrik Stridvallab121e71999-02-04 11:11:01 +000028#include "class.h"
Patrik Stridvalle35d6361998-12-07 09:13:40 +000029#include "x11drv.h"
30
31/**********************************************************************/
32
Patrik Stridvallab121e71999-02-04 11:11:01 +000033extern Cursor X11DRV_MOUSE_XCursor; /* Current X cursor */
Patrik Stridvalle35d6361998-12-07 09:13:40 +000034
35/**********************************************************************/
36
37/* X context to associate a hwnd to an X window */
38XContext winContext = 0;
39
40Atom wmProtocols = None;
41Atom wmDeleteWindow = None;
42Atom dndProtocol = None;
43Atom dndSelection = None;
44
45/***********************************************************************
Patrik Stridvall151170c1998-12-26 12:00:43 +000046 * X11DRV_WND_GetXWindow
Patrik Stridvalle35d6361998-12-07 09:13:40 +000047 *
48 * Return the X window associated to a window.
49 */
Patrik Stridvall151170c1998-12-26 12:00:43 +000050Window X11DRV_WND_GetXWindow(WND *wndPtr)
Patrik Stridvalle35d6361998-12-07 09:13:40 +000051{
Ulrich Weigand4aaf65e1999-02-18 17:30:40 +000052 return wndPtr && wndPtr->pDriverData ?
Patrik Stridvall151170c1998-12-26 12:00:43 +000053 ((X11DRV_WND_DATA *) wndPtr->pDriverData)->window : 0;
54}
55
56/***********************************************************************
57 * X11DRV_WND_FindXWindow
58 *
59 * Return the the first X window associated to a window chain.
60 */
61Window X11DRV_WND_FindXWindow(WND *wndPtr)
62{
63 while (wndPtr &&
64 !((X11DRV_WND_DATA *) wndPtr->pDriverData)->window)
65 wndPtr = wndPtr->parent;
66 return wndPtr ?
67 ((X11DRV_WND_DATA *) wndPtr->pDriverData)->window : 0;
Patrik Stridvalle35d6361998-12-07 09:13:40 +000068}
69
70/***********************************************************************
Patrik Stridvallab121e71999-02-04 11:11:01 +000071 * X11DRV_WND_GetXScreen
72 *
73 * Return the X screen associated to the window.
74 */
75Screen *X11DRV_WND_GetXScreen(WND *wndPtr)
76{
77 while(wndPtr->parent) wndPtr = wndPtr->parent;
78 return X11DRV_DESKTOP_GetXScreen((struct tagDESKTOP *) wndPtr->wExtra);
79}
80
81/***********************************************************************
82 * X11DRV_WND_GetXRootWindow
83 *
84 * Return the X display associated to the window.
85 */
86Window X11DRV_WND_GetXRootWindow(WND *wndPtr)
87{
88 while(wndPtr->parent) wndPtr = wndPtr->parent;
89 return X11DRV_DESKTOP_GetXRootWindow((struct tagDESKTOP *) wndPtr->wExtra);
90}
91
92/***********************************************************************
Patrik Stridvalle35d6361998-12-07 09:13:40 +000093 * X11DRV_WND_RegisterWindow
94 *
95 * Associate an X window to a HWND.
96 */
Patrik Stridvallab121e71999-02-04 11:11:01 +000097static void X11DRV_WND_RegisterWindow(WND *wndPtr)
Patrik Stridvalle35d6361998-12-07 09:13:40 +000098{
Patrik Stridvallab121e71999-02-04 11:11:01 +000099 TSXSetWMProtocols( display, X11DRV_WND_GetXWindow(wndPtr), &wmDeleteWindow, 1 );
Patrik Stridvalle35d6361998-12-07 09:13:40 +0000100
101 if (!winContext) winContext = TSXUniqueContext();
Patrik Stridvallab121e71999-02-04 11:11:01 +0000102 TSXSaveContext( display, X11DRV_WND_GetXWindow(wndPtr), winContext, (char *) wndPtr );
Patrik Stridvall151170c1998-12-26 12:00:43 +0000103}
104
105/**********************************************************************
106 * X11DRV_WND_Initialize
107 */
108void X11DRV_WND_Initialize(WND *wndPtr)
109{
110 X11DRV_WND_DATA *pWndDriverData =
111 (X11DRV_WND_DATA *) HeapAlloc(SystemHeap, 0, sizeof(X11DRV_WND_DATA));
112
113 wndPtr->pDriverData = (void *) pWndDriverData;
114
115 pWndDriverData->window = 0;
116}
117
118/**********************************************************************
119 * X11DRV_WND_Finalize
120 */
121void X11DRV_WND_Finalize(WND *wndPtr)
122{
123 X11DRV_WND_DATA *pWndDriverData =
124 (X11DRV_WND_DATA *) wndPtr->pDriverData;
125
Marcus Meissner308477b1999-01-23 14:03:11 +0000126 if (!wndPtr->pDriverData) {
127 ERR(win,"Trying to destroy window again. Not good.\n");
128 return;
129 }
Patrik Stridvall151170c1998-12-26 12:00:43 +0000130 if(pWndDriverData->window)
131 {
132 ERR(win,
133 "WND destroyed without destroying "
134 "the associated X Window (%ld)\n",
135 pWndDriverData->window
136 );
137 }
138 HeapFree(SystemHeap, 0, wndPtr->pDriverData);
Marcus Meissnerbb7959b1999-01-24 18:55:48 +0000139 wndPtr->pDriverData = NULL;
Patrik Stridvalle35d6361998-12-07 09:13:40 +0000140}
141
142/**********************************************************************
143 * X11DRV_WND_CreateDesktopWindow
144 */
Alexandre Julliarda3960291999-02-26 11:11:13 +0000145BOOL X11DRV_WND_CreateDesktopWindow(WND *wndPtr, CLASS *classPtr, BOOL bUnicode)
Patrik Stridvalle35d6361998-12-07 09:13:40 +0000146{
147 if (wmProtocols == None)
148 wmProtocols = TSXInternAtom( display, "WM_PROTOCOLS", True );
149 if (wmDeleteWindow == None)
150 wmDeleteWindow = TSXInternAtom( display, "WM_DELETE_WINDOW", True );
151 if( dndProtocol == None )
152 dndProtocol = TSXInternAtom( display, "DndProtocol" , False );
153 if( dndSelection == None )
154 dndSelection = TSXInternAtom( display, "DndSelection" , False );
155
Patrik Stridvallab121e71999-02-04 11:11:01 +0000156 ((X11DRV_WND_DATA *) wndPtr->pDriverData)->window =
157 X11DRV_WND_GetXRootWindow( wndPtr );
Patrik Stridvalle35d6361998-12-07 09:13:40 +0000158 X11DRV_WND_RegisterWindow( wndPtr );
159
160 return TRUE;
161}
162
163/**********************************************************************
164 * X11DRV_WND_CreateWindow
165 */
Alexandre Julliarda3960291999-02-26 11:11:13 +0000166BOOL X11DRV_WND_CreateWindow(WND *wndPtr, CLASS *classPtr, CREATESTRUCTA *cs, BOOL bUnicode)
Patrik Stridvalle35d6361998-12-07 09:13:40 +0000167{
168 /* Create the X window (only for top-level windows, and then only */
169 /* when there's no desktop window) */
170
Patrik Stridvallab121e71999-02-04 11:11:01 +0000171 if (!(cs->style & WS_CHILD) &&
172 (X11DRV_WND_GetXRootWindow(wndPtr) == DefaultRootWindow(display)))
Alex Korobka4f1ac051999-03-28 09:37:57 +0000173 {
174 Window wGroupLeader;
175 XWMHints* wm_hints;
Patrik Stridvalle35d6361998-12-07 09:13:40 +0000176 XSetWindowAttributes win_attr;
177
178 if (Options.managed && ((cs->style & (WS_DLGFRAME | WS_THICKFRAME)) ||
179 (cs->dwExStyle & WS_EX_DLGMODALFRAME)))
180 {
181 win_attr.event_mask = ExposureMask | KeyPressMask |
182 KeyReleaseMask | PointerMotionMask |
183 ButtonPressMask | ButtonReleaseMask |
184 FocusChangeMask | StructureNotifyMask;
185 win_attr.override_redirect = FALSE;
186 wndPtr->flags |= WIN_MANAGED;
187 }
188 else
189 {
190 win_attr.event_mask = ExposureMask | KeyPressMask |
191 KeyReleaseMask | PointerMotionMask |
192 ButtonPressMask | ButtonReleaseMask |
193 FocusChangeMask;
194 win_attr.override_redirect = TRUE;
195 }
Alex Korobka4f1ac051999-03-28 09:37:57 +0000196 wndPtr->flags |= WIN_NATIVE;
197
198 win_attr.bit_gravity = BGNorthWest;
Patrik Stridvallb87fe2e1999-04-01 08:16:08 +0000199 win_attr.colormap = X11DRV_PALETTE_PaletteXColormap;
Patrik Stridvalle35d6361998-12-07 09:13:40 +0000200 win_attr.backing_store = Options.backingstore ? WhenMapped : NotUseful;
201 win_attr.save_under = ((classPtr->style & CS_SAVEBITS) != 0);
Patrik Stridvallab121e71999-02-04 11:11:01 +0000202 win_attr.cursor = X11DRV_MOUSE_XCursor;
Alex Korobka4f1ac051999-03-28 09:37:57 +0000203
204 ((X11DRV_WND_DATA *) wndPtr->pDriverData)->bit_gravity = BGNorthWest;
Patrik Stridvall151170c1998-12-26 12:00:43 +0000205 ((X11DRV_WND_DATA *) wndPtr->pDriverData)->window =
Patrik Stridvallab121e71999-02-04 11:11:01 +0000206 TSXCreateWindow( display,
207 X11DRV_WND_GetXRootWindow(wndPtr),
208 cs->x, cs->y, cs->cx, cs->cy,
209 0, CopyFromParent,
Patrik Stridvall151170c1998-12-26 12:00:43 +0000210 InputOutput, CopyFromParent,
211 CWEventMask | CWOverrideRedirect |
212 CWColormap | CWCursor | CWSaveUnder |
Alex Korobka4f1ac051999-03-28 09:37:57 +0000213 CWBackingStore | CWBitGravity,
214 &win_attr );
Patrik Stridvall151170c1998-12-26 12:00:43 +0000215
Alex Korobka4f1ac051999-03-28 09:37:57 +0000216 if(!(wGroupLeader = X11DRV_WND_GetXWindow(wndPtr)))
Patrik Stridvalle35d6361998-12-07 09:13:40 +0000217 return FALSE;
218
Dirk Thierbach9824ec41998-12-15 17:33:04 +0000219 if (wndPtr->flags & WIN_MANAGED) {
220 XClassHint *class_hints = TSXAllocClassHint();
221
222 if (class_hints) {
223 class_hints->res_name = "wineManaged";
224 class_hints->res_class = "Wine";
Patrik Stridvall151170c1998-12-26 12:00:43 +0000225 TSXSetClassHint( display, ((X11DRV_WND_DATA *) wndPtr->pDriverData)->window, class_hints );
Dirk Thierbach9824ec41998-12-15 17:33:04 +0000226 TSXFree (class_hints);
227 }
228
229 if (cs->dwExStyle & WS_EX_DLGMODALFRAME) {
Patrik Stridvalle35d6361998-12-07 09:13:40 +0000230 XSizeHints* size_hints = TSXAllocSizeHints();
231
Dirk Thierbach9824ec41998-12-15 17:33:04 +0000232 if (size_hints) {
Patrik Stridvalle35d6361998-12-07 09:13:40 +0000233 size_hints->min_width = size_hints->max_width = cs->cx;
234 size_hints->min_height = size_hints->max_height = cs->cy;
235 size_hints->flags = (PSize | PMinSize | PMaxSize);
Patrik Stridvall151170c1998-12-26 12:00:43 +0000236 TSXSetWMSizeHints( display, X11DRV_WND_GetXWindow(wndPtr), size_hints,
Patrik Stridvalle35d6361998-12-07 09:13:40 +0000237 XA_WM_NORMAL_HINTS );
238 TSXFree(size_hints);
239 }
240 }
Dirk Thierbach9824ec41998-12-15 17:33:04 +0000241 }
Patrik Stridvalle35d6361998-12-07 09:13:40 +0000242
243 if (cs->hwndParent) /* Get window owner */
Alex Korobka4f1ac051999-03-28 09:37:57 +0000244 {
245 Window w;
Francois Boisvert6b1b41c1999-03-14 17:25:32 +0000246 WND *tmpWnd = WIN_FindWndPtr(cs->hwndParent);
Alex Korobka4f1ac051999-03-28 09:37:57 +0000247
248 w = X11DRV_WND_FindXWindow( tmpWnd );
249 if (w != None)
250 {
251 TSXSetTransientForHint( display, X11DRV_WND_GetXWindow(wndPtr), w );
252 wGroupLeader = w;
253 }
Francois Boisvert6b1b41c1999-03-14 17:25:32 +0000254 WIN_ReleaseWndPtr(tmpWnd);
Alex Korobka4f1ac051999-03-28 09:37:57 +0000255 }
256
257 wm_hints = TSXAllocWMHints();
258 {
259 wm_hints->flags = InputHint | StateHint | WindowGroupHint;
260 wm_hints->input = True;
261 if( wndPtr->dwStyle & WS_VISIBLE )
262 wm_hints->initial_state = (wndPtr->dwStyle & WS_MINIMIZE &&
263 wndPtr->flags & WIN_MANAGED ) ?
264 IconicState : NormalState;
265 else
266 wm_hints->initial_state = WithdrawnState;
267 wm_hints->window_group = wGroupLeader;
268
269 TSXSetWMHints( display, X11DRV_WND_GetXWindow(wndPtr), wm_hints );
270 TSXFree(wm_hints);
271 }
Patrik Stridvalle35d6361998-12-07 09:13:40 +0000272 X11DRV_WND_RegisterWindow( wndPtr );
Alex Korobka4f1ac051999-03-28 09:37:57 +0000273 }
Patrik Stridvalle35d6361998-12-07 09:13:40 +0000274 return TRUE;
275}
276
277/***********************************************************************
278 * X11DRV_WND_DestroyWindow
279 */
Alexandre Julliarda3960291999-02-26 11:11:13 +0000280BOOL X11DRV_WND_DestroyWindow(WND *wndPtr)
Patrik Stridvalle35d6361998-12-07 09:13:40 +0000281{
Patrik Stridvallab121e71999-02-04 11:11:01 +0000282 if (X11DRV_WND_GetXWindow(wndPtr))
Patrik Stridvalle35d6361998-12-07 09:13:40 +0000283 {
284 XEvent xe;
Patrik Stridvallab121e71999-02-04 11:11:01 +0000285 TSXDeleteContext( display, X11DRV_WND_GetXWindow(wndPtr), winContext );
286 TSXDestroyWindow( display, X11DRV_WND_GetXWindow(wndPtr) );
287 while( TSXCheckWindowEvent(display, X11DRV_WND_GetXWindow(wndPtr), NoEventMask, &xe) );
288 ((X11DRV_WND_DATA *) wndPtr->pDriverData)->window = None;
Patrik Stridvalle35d6361998-12-07 09:13:40 +0000289 }
290
291 return TRUE;
292}
293
294/*****************************************************************
295 * X11DRV_WND_SetParent
296 */
297WND *X11DRV_WND_SetParent(WND *wndPtr, WND *pWndParent)
298{
Francois Boisvert6b1b41c1999-03-14 17:25:32 +0000299 WND *pDesktop = WIN_GetDesktop();
300
301 if( wndPtr && pWndParent && (wndPtr != pDesktop) )
Patrik Stridvalle35d6361998-12-07 09:13:40 +0000302 {
303 WND* pWndPrev = wndPtr->parent;
304
305 if( pWndParent != pWndPrev )
306 {
Patrik Stridvall151170c1998-12-26 12:00:43 +0000307 if ( X11DRV_WND_GetXWindow(wndPtr) )
Patrik Stridvalle35d6361998-12-07 09:13:40 +0000308 {
309 /* Toplevel window needs to be reparented. Used by Tk 8.0 */
310
Patrik Stridvall151170c1998-12-26 12:00:43 +0000311 TSXDestroyWindow( display, X11DRV_WND_GetXWindow(wndPtr) );
312 ((X11DRV_WND_DATA *) wndPtr->pDriverData)->window = None;
Patrik Stridvalle35d6361998-12-07 09:13:40 +0000313 }
Patrik Stridvalle35d6361998-12-07 09:13:40 +0000314
315 WIN_UnlinkWindow(wndPtr->hwndSelf);
316 wndPtr->parent = pWndParent;
317
NF Stevense00bb9d1999-01-31 10:01:41 +0000318 /* Create an X counterpart for reparented top-level windows
Patrik Stridvalle35d6361998-12-07 09:13:40 +0000319 * when not in the desktop mode. */
NF Stevense00bb9d1999-01-31 10:01:41 +0000320
Francois Boisvert6b1b41c1999-03-14 17:25:32 +0000321 if( pWndParent == pDesktop )
NF Stevense00bb9d1999-01-31 10:01:41 +0000322 {
323 wndPtr->dwStyle &= ~WS_CHILD;
324 wndPtr->wIDmenu = 0;
Patrik Stridvallab121e71999-02-04 11:11:01 +0000325 if( X11DRV_WND_GetXRootWindow(wndPtr) == DefaultRootWindow(display) )
NF Stevense00bb9d1999-01-31 10:01:41 +0000326 {
Alexandre Julliarda3960291999-02-26 11:11:13 +0000327 CREATESTRUCTA cs;
NF Stevense00bb9d1999-01-31 10:01:41 +0000328 cs.lpCreateParams = NULL;
329 cs.hInstance = 0; /* not used if following call */
330 cs.hMenu = 0; /* not used in following call */
331 cs.hwndParent = pWndParent->hwndSelf;
332 cs.cy = wndPtr->rectWindow.bottom - wndPtr->rectWindow.top;
Pavel Roskina0fd2891999-03-14 13:41:07 +0000333 if (!cs.cy)
334 cs.cy = 1;
NF Stevense00bb9d1999-01-31 10:01:41 +0000335 cs.cx = wndPtr->rectWindow.right - wndPtr->rectWindow.left;
Pavel Roskina0fd2891999-03-14 13:41:07 +0000336 if (!cs.cx)
337 cs.cx = 1;
NF Stevense00bb9d1999-01-31 10:01:41 +0000338 cs.y = wndPtr->rectWindow.top;
339 cs.x = wndPtr->rectWindow.left;
340 cs.style = wndPtr->dwStyle;
341 cs.lpszName = 0; /* not used in following call */
342 cs.lpszClass = 0; /*not used in following call */
343 cs.dwExStyle = wndPtr->dwExStyle;
344 X11DRV_WND_CreateWindow(wndPtr, wndPtr->class,
345 &cs, FALSE);
346 }
347 }
348 else /* a child window */
349 {
350 if( !( wndPtr->dwStyle & WS_CHILD ) )
351 {
352 wndPtr->dwStyle |= WS_CHILD;
353 if( wndPtr->wIDmenu != 0)
354 {
Alexandre Julliarda3960291999-02-26 11:11:13 +0000355 DestroyMenu( (HMENU) wndPtr->wIDmenu );
NF Stevense00bb9d1999-01-31 10:01:41 +0000356 wndPtr->wIDmenu = 0;
357 }
358 }
359 }
Bernd Herdec721121999-01-30 15:50:58 +0000360 WIN_LinkWindow(wndPtr->hwndSelf, HWND_TOP);
Patrik Stridvalle35d6361998-12-07 09:13:40 +0000361 }
Francois Boisvert6b1b41c1999-03-14 17:25:32 +0000362 WIN_ReleaseDesktop();
Patrik Stridvalle35d6361998-12-07 09:13:40 +0000363 return pWndPrev;
364 } /* failure */
Francois Boisvert6b1b41c1999-03-14 17:25:32 +0000365 WIN_ReleaseDesktop();
Patrik Stridvalle35d6361998-12-07 09:13:40 +0000366 return 0;
367}
368
369/***********************************************************************
370 * X11DRV_WND_ForceWindowRaise
371 *
372 * Raise a window on top of the X stacking order, while preserving
373 * the correct Windows Z order.
374 */
Patrik Stridvallab121e71999-02-04 11:11:01 +0000375void X11DRV_WND_ForceWindowRaise(WND *wndPtr)
Patrik Stridvalle35d6361998-12-07 09:13:40 +0000376{
377 XWindowChanges winChanges;
Francois Boisvert6b1b41c1999-03-14 17:25:32 +0000378 WND *wndPrev,*pDesktop = WIN_GetDesktop();
Patrik Stridvalle35d6361998-12-07 09:13:40 +0000379
Patrik Stridvallab121e71999-02-04 11:11:01 +0000380 if( !wndPtr || !X11DRV_WND_GetXWindow(wndPtr) || (wndPtr->flags & WIN_MANAGED) )
Francois Boisvert3a3cd9f1999-03-28 12:42:52 +0000381 {
382 WIN_ReleaseDesktop();
Patrik Stridvalle35d6361998-12-07 09:13:40 +0000383 return;
Francois Boisvert3a3cd9f1999-03-28 12:42:52 +0000384 }
Patrik Stridvalle35d6361998-12-07 09:13:40 +0000385
Patrik Stridvallab121e71999-02-04 11:11:01 +0000386 /* Raise all windows up to wndPtr according to their Z order.
Patrik Stridvalle35d6361998-12-07 09:13:40 +0000387 * (it would be easier with sibling-related Below but it doesn't
388 * work very well with SGI mwm for instance)
389 */
390 winChanges.stack_mode = Above;
Patrik Stridvallab121e71999-02-04 11:11:01 +0000391 while (wndPtr)
Patrik Stridvalle35d6361998-12-07 09:13:40 +0000392 {
Patrik Stridvallab121e71999-02-04 11:11:01 +0000393 if (X11DRV_WND_GetXWindow(wndPtr))
394 TSXReconfigureWMWindow( display, X11DRV_WND_GetXWindow(wndPtr), 0,
Patrik Stridvall151170c1998-12-26 12:00:43 +0000395 CWStackMode, &winChanges );
Francois Boisvert6b1b41c1999-03-14 17:25:32 +0000396 wndPrev = pDesktop->child;
Patrik Stridvallab121e71999-02-04 11:11:01 +0000397 if (wndPrev == wndPtr) break;
398 while (wndPrev && (wndPrev->next != wndPtr)) wndPrev = wndPrev->next;
399 wndPtr = wndPrev;
Patrik Stridvalle35d6361998-12-07 09:13:40 +0000400 }
Francois Boisvert6b1b41c1999-03-14 17:25:32 +0000401 WIN_ReleaseDesktop();
Patrik Stridvalle35d6361998-12-07 09:13:40 +0000402}
403
404/***********************************************************************
405 * X11DRV_WND_FindDesktopXWindow [Internal]
406 *
407 * Find the actual X window which needs be restacked.
408 * Used by X11DRV_SetWindowPos().
409 */
410static Window X11DRV_WND_FindDesktopXWindow( WND *wndPtr )
411{
412 if (!(wndPtr->flags & WIN_MANAGED))
Patrik Stridvall151170c1998-12-26 12:00:43 +0000413 return X11DRV_WND_GetXWindow(wndPtr);
Patrik Stridvalle35d6361998-12-07 09:13:40 +0000414 else
415 {
416 Window window, root, parent, *children;
417 int nchildren;
Patrik Stridvall151170c1998-12-26 12:00:43 +0000418 window = X11DRV_WND_GetXWindow(wndPtr);
Patrik Stridvalle35d6361998-12-07 09:13:40 +0000419 for (;;)
420 {
421 TSXQueryTree( display, window, &root, &parent,
422 &children, &nchildren );
423 TSXFree( children );
424 if (parent == root)
425 return window;
426 window = parent;
427 }
428 }
429}
430
431/***********************************************************************
432 * WINPOS_SetXWindowPos
433 *
434 * SetWindowPos() for an X window. Used by the real SetWindowPos().
435 */
Alex Korobka4f1ac051999-03-28 09:37:57 +0000436void X11DRV_WND_SetWindowPos(WND *wndPtr, const WINDOWPOS *winpos, BOOL bChangePos)
Patrik Stridvalle35d6361998-12-07 09:13:40 +0000437{
Alex Korobka4f1ac051999-03-28 09:37:57 +0000438 XWindowChanges winChanges;
439 int changeMask = 0;
440 WND *winposPtr = WIN_FindWndPtr( winpos->hwnd );
Patrik Stridvallab121e71999-02-04 11:11:01 +0000441
Alex Korobka4f1ac051999-03-28 09:37:57 +0000442 if(!wndPtr->hwndSelf) wndPtr = NULL; /* FIXME: WND destroyed, shouldn't happend!!! */
Patrik Stridvalle35d6361998-12-07 09:13:40 +0000443
Alex Korobka4f1ac051999-03-28 09:37:57 +0000444 if (!(winpos->flags & SWP_SHOWWINDOW) && (winpos->flags & SWP_HIDEWINDOW))
Patrik Stridvalle35d6361998-12-07 09:13:40 +0000445 {
Patrik Stridvall151170c1998-12-26 12:00:43 +0000446 if(X11DRV_WND_GetXWindow(wndPtr))
447 TSXUnmapWindow( display, X11DRV_WND_GetXWindow(wndPtr) );
Patrik Stridvalle35d6361998-12-07 09:13:40 +0000448 }
449
Alex Korobka4f1ac051999-03-28 09:37:57 +0000450 if(bChangePos)
Patrik Stridvalle35d6361998-12-07 09:13:40 +0000451 {
452 if ( !(winpos->flags & SWP_NOSIZE))
453 {
Alex Korobka4f1ac051999-03-28 09:37:57 +0000454 winChanges.width = (winpos->cx > 0 ) ? winpos->cx : 1;
455 winChanges.height = (winpos->cy > 0 ) ? winpos->cy : 1;
Patrik Stridvalle35d6361998-12-07 09:13:40 +0000456 changeMask |= CWWidth | CWHeight;
457
458 /* Tweak dialog window size hints */
459
460 if ((winposPtr->flags & WIN_MANAGED) &&
461 (winposPtr->dwExStyle & WS_EX_DLGMODALFRAME))
462 {
463 XSizeHints *size_hints = TSXAllocSizeHints();
464
465 if (size_hints)
466 {
467 long supplied_return;
468
Patrik Stridvall151170c1998-12-26 12:00:43 +0000469 TSXGetWMSizeHints( display, X11DRV_WND_GetXWindow(winposPtr), size_hints,
Patrik Stridvalle35d6361998-12-07 09:13:40 +0000470 &supplied_return, XA_WM_NORMAL_HINTS);
471 size_hints->min_width = size_hints->max_width = winpos->cx;
472 size_hints->min_height = size_hints->max_height = winpos->cy;
Patrik Stridvall151170c1998-12-26 12:00:43 +0000473 TSXSetWMSizeHints( display, X11DRV_WND_GetXWindow(winposPtr), size_hints,
Patrik Stridvalle35d6361998-12-07 09:13:40 +0000474 XA_WM_NORMAL_HINTS );
475 TSXFree(size_hints);
476 }
477 }
478 }
479 if (!(winpos->flags & SWP_NOMOVE))
480 {
481 winChanges.x = winpos->x;
482 winChanges.y = winpos->y;
483 changeMask |= CWX | CWY;
484 }
485 if (!(winpos->flags & SWP_NOZORDER))
486 {
487 winChanges.stack_mode = Below;
488 changeMask |= CWStackMode;
489
490 if (winpos->hwndInsertAfter == HWND_TOP) winChanges.stack_mode = Above;
491 else if (winpos->hwndInsertAfter != HWND_BOTTOM)
492 {
493 WND* insertPtr = WIN_FindWndPtr( winpos->hwndInsertAfter );
494 Window stack[2];
495
496 stack[0] = X11DRV_WND_FindDesktopXWindow( insertPtr );
497 stack[1] = X11DRV_WND_FindDesktopXWindow( winposPtr );
498
499 /* for stupid window managers (i.e. all of them) */
500
501 TSXRestackWindows(display, stack, 2);
502 changeMask &= ~CWStackMode;
Francois Boisvert6b1b41c1999-03-14 17:25:32 +0000503
504 WIN_ReleaseWndPtr(insertPtr);
Patrik Stridvalle35d6361998-12-07 09:13:40 +0000505 }
506 }
507 if (changeMask)
508 {
Patrik Stridvall151170c1998-12-26 12:00:43 +0000509 TSXReconfigureWMWindow( display, X11DRV_WND_GetXWindow(winposPtr), 0, changeMask, &winChanges );
Patrik Stridvalle35d6361998-12-07 09:13:40 +0000510 }
511 }
512
Alex Korobka4f1ac051999-03-28 09:37:57 +0000513 if ( winpos->flags & SWP_SHOWWINDOW )
Patrik Stridvalle35d6361998-12-07 09:13:40 +0000514 {
Patrik Stridvall151170c1998-12-26 12:00:43 +0000515 if(X11DRV_WND_GetXWindow(wndPtr)) TSXMapWindow( display, X11DRV_WND_GetXWindow(wndPtr) );
Patrik Stridvalle35d6361998-12-07 09:13:40 +0000516 }
Alex Korobka4f1ac051999-03-28 09:37:57 +0000517 WIN_ReleaseWndPtr(winposPtr);
Patrik Stridvalle35d6361998-12-07 09:13:40 +0000518}
519
520/*****************************************************************
521 * X11DRV_WND_SetText
522 */
523void X11DRV_WND_SetText(WND *wndPtr, LPCSTR text)
524{
Patrik Stridvall151170c1998-12-26 12:00:43 +0000525 if (!X11DRV_WND_GetXWindow(wndPtr))
Patrik Stridvalle35d6361998-12-07 09:13:40 +0000526 return;
527
Patrik Stridvall151170c1998-12-26 12:00:43 +0000528 TSXStoreName( display, X11DRV_WND_GetXWindow(wndPtr), text );
529 TSXSetIconName( display, X11DRV_WND_GetXWindow(wndPtr), text );
Patrik Stridvalle35d6361998-12-07 09:13:40 +0000530}
531
532/*****************************************************************
533 * X11DRV_WND_SetFocus
534 *
535 * Set the X focus.
536 * Explicit colormap management seems to work only with OLVWM.
537 */
538void X11DRV_WND_SetFocus(WND *wndPtr)
539{
Alexandre Julliarda3960291999-02-26 11:11:13 +0000540 HWND hwnd = wndPtr->hwndSelf;
Patrik Stridvalle35d6361998-12-07 09:13:40 +0000541 XWindowAttributes win_attr;
Alexandre Julliard68420641998-12-27 15:26:28 +0000542 Window win;
Patrik Stridvalle35d6361998-12-07 09:13:40 +0000543
544 /* Only mess with the X focus if there's */
545 /* no desktop window and no window manager. */
Patrik Stridvallab121e71999-02-04 11:11:01 +0000546 if ((X11DRV_WND_GetXRootWindow(wndPtr) != DefaultRootWindow(display))
547 || Options.managed) return;
Patrik Stridvalle35d6361998-12-07 09:13:40 +0000548
549 if (!hwnd) /* If setting the focus to 0, uninstall the colormap */
550 {
Patrik Stridvallb87fe2e1999-04-01 08:16:08 +0000551 if (X11DRV_PALETTE_PaletteFlags & X11DRV_PALETTE_PRIVATE)
552 TSXUninstallColormap( display, X11DRV_PALETTE_PaletteXColormap );
Patrik Stridvalle35d6361998-12-07 09:13:40 +0000553 return;
554 }
555
556 /* Set X focus and install colormap */
557
Alexandre Julliard68420641998-12-27 15:26:28 +0000558 if (!(win = X11DRV_WND_FindXWindow(wndPtr))) return;
559 if (!TSXGetWindowAttributes( display, win, &win_attr ) ||
Patrik Stridvalle35d6361998-12-07 09:13:40 +0000560 (win_attr.map_state != IsViewable))
561 return; /* If window is not viewable, don't change anything */
562
Alexandre Julliard68420641998-12-27 15:26:28 +0000563 TSXSetInputFocus( display, win, RevertToParent, CurrentTime );
Patrik Stridvallb87fe2e1999-04-01 08:16:08 +0000564 if (X11DRV_PALETTE_PaletteFlags & X11DRV_PALETTE_PRIVATE)
565 TSXInstallColormap( display, X11DRV_PALETTE_PaletteXColormap );
Patrik Stridvalle35d6361998-12-07 09:13:40 +0000566
567 EVENT_Synchronize();
568}
569
570/*****************************************************************
571 * X11DRV_WND_PreSizeMove
572 */
573void X11DRV_WND_PreSizeMove(WND *wndPtr)
574{
Patrik Stridvallab121e71999-02-04 11:11:01 +0000575 if (!(wndPtr->dwStyle & WS_CHILD) &&
576 (X11DRV_WND_GetXRootWindow(wndPtr) == DefaultRootWindow(display)))
Patrik Stridvalle35d6361998-12-07 09:13:40 +0000577 TSXGrabServer( display );
578}
579
580/*****************************************************************
581 * X11DRV_WND_PostSizeMove
582 */
583void X11DRV_WND_PostSizeMove(WND *wndPtr)
584{
Patrik Stridvallab121e71999-02-04 11:11:01 +0000585 if (!(wndPtr->dwStyle & WS_CHILD) &&
Jerome Vouillon1da6dba1999-02-14 13:32:13 +0000586 (X11DRV_GetXRootWindow() == DefaultRootWindow(display)))
Patrik Stridvalle35d6361998-12-07 09:13:40 +0000587 TSXUngrabServer( display );
588}
589
Patrik Stridvall151170c1998-12-26 12:00:43 +0000590/*****************************************************************
Alex Korobka4f1ac051999-03-28 09:37:57 +0000591 * X11DRV_WND_SurfaceCopy
592 *
593 * Copies rect to (rect.left + dx, rect.top + dy).
Patrik Stridvall151170c1998-12-26 12:00:43 +0000594 */
Alex Korobka4f1ac051999-03-28 09:37:57 +0000595void X11DRV_WND_SurfaceCopy(WND* wndPtr, DC *dcPtr, INT dx, INT dy,
596 const RECT *rect, BOOL bUpdate)
Patrik Stridvall151170c1998-12-26 12:00:43 +0000597{
Alex Korobka4f1ac051999-03-28 09:37:57 +0000598 X11DRV_PDEVICE *physDev = (X11DRV_PDEVICE *)dcPtr->physDev;
599 POINT dst, src;
Patrik Stridvall151170c1998-12-26 12:00:43 +0000600
Alex Korobka4f1ac051999-03-28 09:37:57 +0000601 dst.x = (src.x = dcPtr->w.DCOrgX + rect->left) + dx;
602 dst.y = (src.y = dcPtr->w.DCOrgY + rect->top) + dy;
Patrik Stridvall151170c1998-12-26 12:00:43 +0000603
Alex Korobka4f1ac051999-03-28 09:37:57 +0000604 if (bUpdate) /* handles non-Wine windows hanging over the copied area */
605 TSXSetGraphicsExposures( display, physDev->gc, True );
606 TSXSetFunction( display, physDev->gc, GXcopy );
607 TSXCopyArea( display, physDev->drawable, physDev->drawable,
608 physDev->gc, src.x, src.y,
609 rect->right - rect->left,
610 rect->bottom - rect->top,
611 dst.x, dst.y );
612 if (bUpdate)
613 TSXSetGraphicsExposures( display, physDev->gc, False );
Jerome Vouillon1da6dba1999-02-14 13:32:13 +0000614
Alex Korobka4f1ac051999-03-28 09:37:57 +0000615 if (bUpdate) /* Make sure exposure events have been processed */
616 EVENT_Synchronize();
Patrik Stridvall151170c1998-12-26 12:00:43 +0000617}
618
619/***********************************************************************
620 * X11DRV_WND_SetDrawable
621 *
622 * Set the drawable, origin and dimensions for the DC associated to
623 * a given window.
624 */
Alexandre Julliarda3960291999-02-26 11:11:13 +0000625void X11DRV_WND_SetDrawable(WND *wndPtr, DC *dc, WORD flags, BOOL bSetClipOrigin)
Patrik Stridvall151170c1998-12-26 12:00:43 +0000626{
627 X11DRV_PDEVICE *physDev = (X11DRV_PDEVICE *)dc->physDev;
628
629 if (!wndPtr) /* Get a DC for the whole screen */
630 {
631 dc->w.DCOrgX = 0;
632 dc->w.DCOrgY = 0;
Patrik Stridvallab121e71999-02-04 11:11:01 +0000633 physDev->drawable = X11DRV_WND_GetXRootWindow(wndPtr);
Patrik Stridvall151170c1998-12-26 12:00:43 +0000634 TSXSetSubwindowMode( display, physDev->gc, IncludeInferiors );
635 }
636 else
637 {
638 if (flags & DCX_WINDOW)
639 {
640 dc->w.DCOrgX = wndPtr->rectWindow.left;
641 dc->w.DCOrgY = wndPtr->rectWindow.top;
642 }
643 else
644 {
645 dc->w.DCOrgX = wndPtr->rectClient.left;
646 dc->w.DCOrgY = wndPtr->rectClient.top;
647 }
648 while (!X11DRV_WND_GetXWindow(wndPtr))
649 {
650 wndPtr = wndPtr->parent;
651 dc->w.DCOrgX += wndPtr->rectClient.left;
652 dc->w.DCOrgY += wndPtr->rectClient.top;
653 }
654 dc->w.DCOrgX -= wndPtr->rectWindow.left;
655 dc->w.DCOrgY -= wndPtr->rectWindow.top;
656 physDev->drawable = X11DRV_WND_GetXWindow(wndPtr);
657
658#if 0
659 /* This is needed when we reuse a cached DC because
660 * SetDCState() called by ReleaseDC() screws up DC
661 * origins for child windows.
662 */
663
664 if( bSetClipOrigin )
665 TSXSetClipOrigin( display, physDev->gc, dc->w.DCOrgX, dc->w.DCOrgY );
666#endif
667 }
668}
669
670/***********************************************************************
Alex Korobka4f1ac051999-03-28 09:37:57 +0000671 * X11DRV_WND_SetHostAttr
672 */
673BOOL X11DRV_WND_SetHostAttr(WND* wnd, INT ha, INT value)
674{
675 Window w;
676
677 if( (w = X11DRV_WND_GetXWindow(wnd)) )
678 {
679 XSetWindowAttributes win_attr;
680
681 switch( ha )
682 {
683 case HAK_BITGRAVITY:
684
685 if( ((X11DRV_WND_DATA *) wnd->pDriverData)->bit_gravity != value )
686 {
687 win_attr.bit_gravity = value;
688 ((X11DRV_WND_DATA *) wnd->pDriverData)->bit_gravity = value;
689 TSXChangeWindowAttributes( display, w, CWBitGravity, &win_attr );
690 }
691 return TRUE;
692
693 case HAK_ACCEPTFOCUS:
694
695 if( (wnd->flags & WIN_MANAGED) )
696 {
697 XWMHints* wm_hints = TSXAllocWMHints();
698
699 if( wm_hints )
700 {
701 wm_hints->flags = InputHint;
702 wm_hints->input = value;
703 TSXSetWMHints( display, X11DRV_WND_GetXWindow(wnd), wm_hints );
704 TSXFree( wm_hints );
705 return TRUE;
706 }
707 }
708 break;
709 }
710 }
711 return FALSE;
712}
713
714/***********************************************************************
Patrik Stridvall151170c1998-12-26 12:00:43 +0000715 * X11DRV_WND_IsSelfClipping
716 */
Alexandre Julliarda3960291999-02-26 11:11:13 +0000717BOOL X11DRV_WND_IsSelfClipping(WND *wndPtr)
Patrik Stridvall151170c1998-12-26 12:00:43 +0000718{
Patrik Stridvallb87fe2e1999-04-01 08:16:08 +0000719 return X11DRV_WND_GetXWindow(wndPtr) != None;
Patrik Stridvall151170c1998-12-26 12:00:43 +0000720}
721
Patrik Stridvalle35d6361998-12-07 09:13:40 +0000722#endif /* !defined(X_DISPLAY_MISSING) */