4 * Copyright 1993, 1994, 1995, 1996 Alexandre Julliard
6 * 1995, 1996 Alex Korobka
11 #ifndef X_DISPLAY_MISSING
13 #include <X11/Xatom.h>
31 /**********************************************************************/
33 extern Cursor X11DRV_MOUSE_XCursor
; /* Current X cursor */
35 /**********************************************************************/
37 /* X context to associate a hwnd to an X window */
38 XContext winContext
= 0;
40 Atom wmProtocols
= None
;
41 Atom wmDeleteWindow
= None
;
42 Atom dndProtocol
= None
;
43 Atom dndSelection
= None
;
45 /***********************************************************************
46 * X11DRV_WND_GetXWindow
48 * Return the X window associated to a window.
50 Window
X11DRV_WND_GetXWindow(WND
*wndPtr
)
53 ((X11DRV_WND_DATA
*) wndPtr
->pDriverData
)->window
: 0;
56 /***********************************************************************
57 * X11DRV_WND_FindXWindow
59 * Return the the first X window associated to a window chain.
61 Window
X11DRV_WND_FindXWindow(WND
*wndPtr
)
64 !((X11DRV_WND_DATA
*) wndPtr
->pDriverData
)->window
)
65 wndPtr
= wndPtr
->parent
;
67 ((X11DRV_WND_DATA
*) wndPtr
->pDriverData
)->window
: 0;
70 /***********************************************************************
71 * X11DRV_WND_GetXScreen
73 * Return the X screen associated to the window.
75 Screen
*X11DRV_WND_GetXScreen(WND
*wndPtr
)
77 while(wndPtr
->parent
) wndPtr
= wndPtr
->parent
;
78 return X11DRV_DESKTOP_GetXScreen((struct tagDESKTOP
*) wndPtr
->wExtra
);
81 /***********************************************************************
82 * X11DRV_WND_GetXRootWindow
84 * Return the X display associated to the window.
86 Window
X11DRV_WND_GetXRootWindow(WND
*wndPtr
)
88 while(wndPtr
->parent
) wndPtr
= wndPtr
->parent
;
89 return X11DRV_DESKTOP_GetXRootWindow((struct tagDESKTOP
*) wndPtr
->wExtra
);
92 /***********************************************************************
93 * X11DRV_WND_RegisterWindow
95 * Associate an X window to a HWND.
97 static void X11DRV_WND_RegisterWindow(WND
*wndPtr
)
99 TSXSetWMProtocols( display
, X11DRV_WND_GetXWindow(wndPtr
), &wmDeleteWindow
, 1 );
101 if (!winContext
) winContext
= TSXUniqueContext();
102 TSXSaveContext( display
, X11DRV_WND_GetXWindow(wndPtr
), winContext
, (char *) wndPtr
);
105 /**********************************************************************
106 * X11DRV_WND_Initialize
108 void X11DRV_WND_Initialize(WND
*wndPtr
)
110 X11DRV_WND_DATA
*pWndDriverData
=
111 (X11DRV_WND_DATA
*) HeapAlloc(SystemHeap
, 0, sizeof(X11DRV_WND_DATA
));
113 wndPtr
->pDriverData
= (void *) pWndDriverData
;
115 pWndDriverData
->window
= 0;
118 /**********************************************************************
119 * X11DRV_WND_Finalize
121 void X11DRV_WND_Finalize(WND
*wndPtr
)
123 X11DRV_WND_DATA
*pWndDriverData
=
124 (X11DRV_WND_DATA
*) wndPtr
->pDriverData
;
126 if (!wndPtr
->pDriverData
) {
127 ERR(win
,"Trying to destroy window again. Not good.\n");
130 if(pWndDriverData
->window
)
133 "WND destroyed without destroying "
134 "the associated X Window (%ld)\n",
135 pWndDriverData
->window
138 HeapFree(SystemHeap
, 0, wndPtr
->pDriverData
);
139 wndPtr
->pDriverData
= NULL
;
142 /**********************************************************************
143 * X11DRV_WND_CreateDesktopWindow
145 BOOL32
X11DRV_WND_CreateDesktopWindow(WND
*wndPtr
, CLASS
*classPtr
, BOOL32 bUnicode
)
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
);
156 ((X11DRV_WND_DATA
*) wndPtr
->pDriverData
)->window
=
157 X11DRV_WND_GetXRootWindow( wndPtr
);
158 X11DRV_WND_RegisterWindow( wndPtr
);
163 /**********************************************************************
164 * X11DRV_WND_CreateWindow
166 BOOL32
X11DRV_WND_CreateWindow(WND
*wndPtr
, CLASS
*classPtr
, CREATESTRUCT32A
*cs
, BOOL32 bUnicode
)
168 /* Create the X window (only for top-level windows, and then only */
169 /* when there's no desktop window) */
171 if (!(cs
->style
& WS_CHILD
) &&
172 (X11DRV_WND_GetXRootWindow(wndPtr
) == DefaultRootWindow(display
)))
174 XSetWindowAttributes win_attr
;
176 if (Options
.managed
&& ((cs
->style
& (WS_DLGFRAME
| WS_THICKFRAME
)) ||
177 (cs
->dwExStyle
& WS_EX_DLGMODALFRAME
)))
179 win_attr
.event_mask
= ExposureMask
| KeyPressMask
|
180 KeyReleaseMask
| PointerMotionMask
|
181 ButtonPressMask
| ButtonReleaseMask
|
182 FocusChangeMask
| StructureNotifyMask
;
183 win_attr
.override_redirect
= FALSE
;
184 wndPtr
->flags
|= WIN_MANAGED
;
188 win_attr
.event_mask
= ExposureMask
| KeyPressMask
|
189 KeyReleaseMask
| PointerMotionMask
|
190 ButtonPressMask
| ButtonReleaseMask
|
192 win_attr
.override_redirect
= TRUE
;
194 win_attr
.colormap
= X11DRV_COLOR_GetColormap();
195 win_attr
.backing_store
= Options
.backingstore
? WhenMapped
: NotUseful
;
196 win_attr
.save_under
= ((classPtr
->style
& CS_SAVEBITS
) != 0);
197 win_attr
.cursor
= X11DRV_MOUSE_XCursor
;
198 ((X11DRV_WND_DATA
*) wndPtr
->pDriverData
)->window
=
199 TSXCreateWindow( display
,
200 X11DRV_WND_GetXRootWindow(wndPtr
),
201 cs
->x
, cs
->y
, cs
->cx
, cs
->cy
,
203 InputOutput
, CopyFromParent
,
204 CWEventMask
| CWOverrideRedirect
|
205 CWColormap
| CWCursor
| CWSaveUnder
|
206 CWBackingStore
, &win_attr
);
208 if(!X11DRV_WND_GetXWindow(wndPtr
))
211 if (wndPtr
->flags
& WIN_MANAGED
) {
212 XClassHint
*class_hints
= TSXAllocClassHint();
215 class_hints
->res_name
= "wineManaged";
216 class_hints
->res_class
= "Wine";
217 TSXSetClassHint( display
, ((X11DRV_WND_DATA
*) wndPtr
->pDriverData
)->window
, class_hints
);
218 TSXFree (class_hints
);
221 if (cs
->dwExStyle
& WS_EX_DLGMODALFRAME
) {
222 XSizeHints
* size_hints
= TSXAllocSizeHints();
225 size_hints
->min_width
= size_hints
->max_width
= cs
->cx
;
226 size_hints
->min_height
= size_hints
->max_height
= cs
->cy
;
227 size_hints
->flags
= (PSize
| PMinSize
| PMaxSize
);
228 TSXSetWMSizeHints( display
, X11DRV_WND_GetXWindow(wndPtr
), size_hints
,
229 XA_WM_NORMAL_HINTS
);
235 if (cs
->hwndParent
) /* Get window owner */
237 Window win
= X11DRV_WND_FindXWindow( WIN_FindWndPtr( cs
->hwndParent
) );
238 if (win
) TSXSetTransientForHint( display
, X11DRV_WND_GetXWindow(wndPtr
), win
);
240 X11DRV_WND_RegisterWindow( wndPtr
);
245 /***********************************************************************
246 * X11DRV_WND_DestroyWindow
248 BOOL32
X11DRV_WND_DestroyWindow(WND
*wndPtr
)
250 if (X11DRV_WND_GetXWindow(wndPtr
))
253 TSXDeleteContext( display
, X11DRV_WND_GetXWindow(wndPtr
), winContext
);
254 TSXDestroyWindow( display
, X11DRV_WND_GetXWindow(wndPtr
) );
255 while( TSXCheckWindowEvent(display
, X11DRV_WND_GetXWindow(wndPtr
), NoEventMask
, &xe
) );
256 ((X11DRV_WND_DATA
*) wndPtr
->pDriverData
)->window
= None
;
262 /*****************************************************************
263 * X11DRV_WND_SetParent
265 WND
*X11DRV_WND_SetParent(WND
*wndPtr
, WND
*pWndParent
)
267 if( wndPtr
&& pWndParent
&& (wndPtr
!= WIN_GetDesktop()) )
269 WND
* pWndPrev
= wndPtr
->parent
;
271 if( pWndParent
!= pWndPrev
)
273 if ( X11DRV_WND_GetXWindow(wndPtr
) )
275 /* Toplevel window needs to be reparented. Used by Tk 8.0 */
277 TSXDestroyWindow( display
, X11DRV_WND_GetXWindow(wndPtr
) );
278 ((X11DRV_WND_DATA
*) wndPtr
->pDriverData
)->window
= None
;
281 WIN_UnlinkWindow(wndPtr
->hwndSelf
);
282 wndPtr
->parent
= pWndParent
;
284 /* Create an X counterpart for reparented top-level windows
285 * when not in the desktop mode. */
287 if( pWndParent
== WIN_GetDesktop () )
289 wndPtr
->dwStyle
&= ~WS_CHILD
;
291 if( X11DRV_WND_GetXRootWindow(wndPtr
) == DefaultRootWindow(display
) )
294 cs
.lpCreateParams
= NULL
;
295 cs
.hInstance
= 0; /* not used if following call */
296 cs
.hMenu
= 0; /* not used in following call */
297 cs
.hwndParent
= pWndParent
->hwndSelf
;
298 cs
.cy
= wndPtr
->rectWindow
.bottom
- wndPtr
->rectWindow
.top
;
299 cs
.cx
= wndPtr
->rectWindow
.right
- wndPtr
->rectWindow
.left
;
300 cs
.y
= wndPtr
->rectWindow
.top
;
301 cs
.x
= wndPtr
->rectWindow
.left
;
302 cs
.style
= wndPtr
->dwStyle
;
303 cs
.lpszName
= 0; /* not used in following call */
304 cs
.lpszClass
= 0; /*not used in following call */
305 cs
.dwExStyle
= wndPtr
->dwExStyle
;
306 X11DRV_WND_CreateWindow(wndPtr
, wndPtr
->class,
310 else /* a child window */
312 if( !( wndPtr
->dwStyle
& WS_CHILD
) )
314 wndPtr
->dwStyle
|= WS_CHILD
;
315 if( wndPtr
->wIDmenu
!= 0)
317 DestroyMenu32( (HMENU32
) wndPtr
->wIDmenu
);
322 WIN_LinkWindow(wndPtr
->hwndSelf
, HWND_TOP
);
329 /***********************************************************************
330 * X11DRV_WND_ForceWindowRaise
332 * Raise a window on top of the X stacking order, while preserving
333 * the correct Windows Z order.
335 void X11DRV_WND_ForceWindowRaise(WND
*wndPtr
)
337 XWindowChanges winChanges
;
340 if( !wndPtr
|| !X11DRV_WND_GetXWindow(wndPtr
) || (wndPtr
->flags
& WIN_MANAGED
) )
343 /* Raise all windows up to wndPtr according to their Z order.
344 * (it would be easier with sibling-related Below but it doesn't
345 * work very well with SGI mwm for instance)
347 winChanges
.stack_mode
= Above
;
350 if (X11DRV_WND_GetXWindow(wndPtr
))
351 TSXReconfigureWMWindow( display
, X11DRV_WND_GetXWindow(wndPtr
), 0,
352 CWStackMode
, &winChanges
);
353 wndPrev
= WIN_GetDesktop()->child
;
354 if (wndPrev
== wndPtr
) break;
355 while (wndPrev
&& (wndPrev
->next
!= wndPtr
)) wndPrev
= wndPrev
->next
;
360 /***********************************************************************
361 * X11DRV_WND_FindDesktopXWindow [Internal]
363 * Find the actual X window which needs be restacked.
364 * Used by X11DRV_SetWindowPos().
366 static Window
X11DRV_WND_FindDesktopXWindow( WND
*wndPtr
)
368 if (!(wndPtr
->flags
& WIN_MANAGED
))
369 return X11DRV_WND_GetXWindow(wndPtr
);
372 Window window
, root
, parent
, *children
;
374 window
= X11DRV_WND_GetXWindow(wndPtr
);
377 TSXQueryTree( display
, window
, &root
, &parent
,
378 &children
, &nchildren
);
387 /***********************************************************************
388 * WINPOS_SetXWindowPos
390 * SetWindowPos() for an X window. Used by the real SetWindowPos().
392 void X11DRV_WND_SetWindowPos(WND
*wndPtr
, const WINDOWPOS32
*winpos
, BOOL32 bSMC_SETXPOS
)
394 XWindowChanges winChanges
;
396 WND
*winposPtr
= WIN_FindWndPtr( winpos
->hwnd
);
398 if(!wndPtr
->hwndSelf
) wndPtr
= NULL
; /* FIXME: WND destroyed, shouldn't happend!!! */
400 if (!(winpos
->flags
& SWP_SHOWWINDOW
) && (winpos
->flags
& SWP_HIDEWINDOW
))
402 if(X11DRV_WND_GetXWindow(wndPtr
))
403 TSXUnmapWindow( display
, X11DRV_WND_GetXWindow(wndPtr
) );
408 if ( !(winpos
->flags
& SWP_NOSIZE
))
410 winChanges
.width
= winpos
->cx
;
411 winChanges
.height
= winpos
->cy
;
412 changeMask
|= CWWidth
| CWHeight
;
414 /* Tweak dialog window size hints */
416 if ((winposPtr
->flags
& WIN_MANAGED
) &&
417 (winposPtr
->dwExStyle
& WS_EX_DLGMODALFRAME
))
419 XSizeHints
*size_hints
= TSXAllocSizeHints();
423 long supplied_return
;
425 TSXGetWMSizeHints( display
, X11DRV_WND_GetXWindow(winposPtr
), size_hints
,
426 &supplied_return
, XA_WM_NORMAL_HINTS
);
427 size_hints
->min_width
= size_hints
->max_width
= winpos
->cx
;
428 size_hints
->min_height
= size_hints
->max_height
= winpos
->cy
;
429 TSXSetWMSizeHints( display
, X11DRV_WND_GetXWindow(winposPtr
), size_hints
,
430 XA_WM_NORMAL_HINTS
);
435 if (!(winpos
->flags
& SWP_NOMOVE
))
437 winChanges
.x
= winpos
->x
;
438 winChanges
.y
= winpos
->y
;
439 changeMask
|= CWX
| CWY
;
441 if (!(winpos
->flags
& SWP_NOZORDER
))
443 winChanges
.stack_mode
= Below
;
444 changeMask
|= CWStackMode
;
446 if (winpos
->hwndInsertAfter
== HWND_TOP
) winChanges
.stack_mode
= Above
;
447 else if (winpos
->hwndInsertAfter
!= HWND_BOTTOM
)
449 WND
* insertPtr
= WIN_FindWndPtr( winpos
->hwndInsertAfter
);
452 stack
[0] = X11DRV_WND_FindDesktopXWindow( insertPtr
);
453 stack
[1] = X11DRV_WND_FindDesktopXWindow( winposPtr
);
455 /* for stupid window managers (i.e. all of them) */
457 TSXRestackWindows(display
, stack
, 2);
458 changeMask
&= ~CWStackMode
;
463 TSXReconfigureWMWindow( display
, X11DRV_WND_GetXWindow(winposPtr
), 0, changeMask
, &winChanges
);
467 if ( winpos
->flags
& SWP_SHOWWINDOW
)
469 if(X11DRV_WND_GetXWindow(wndPtr
)) TSXMapWindow( display
, X11DRV_WND_GetXWindow(wndPtr
) );
473 /*****************************************************************
476 void X11DRV_WND_SetText(WND
*wndPtr
, LPCSTR text
)
478 if (!X11DRV_WND_GetXWindow(wndPtr
))
481 TSXStoreName( display
, X11DRV_WND_GetXWindow(wndPtr
), text
);
482 TSXSetIconName( display
, X11DRV_WND_GetXWindow(wndPtr
), text
);
485 /*****************************************************************
486 * X11DRV_WND_SetFocus
489 * Explicit colormap management seems to work only with OLVWM.
491 void X11DRV_WND_SetFocus(WND
*wndPtr
)
493 HWND32 hwnd
= wndPtr
->hwndSelf
;
494 XWindowAttributes win_attr
;
497 /* Only mess with the X focus if there's */
498 /* no desktop window and no window manager. */
499 if ((X11DRV_WND_GetXRootWindow(wndPtr
) != DefaultRootWindow(display
))
500 || Options
.managed
) return;
502 if (!hwnd
) /* If setting the focus to 0, uninstall the colormap */
504 if (COLOR_GetSystemPaletteFlags() & COLOR_PRIVATE
)
505 TSXUninstallColormap( display
, X11DRV_COLOR_GetColormap() );
509 /* Set X focus and install colormap */
511 if (!(win
= X11DRV_WND_FindXWindow(wndPtr
))) return;
512 if (!TSXGetWindowAttributes( display
, win
, &win_attr
) ||
513 (win_attr
.map_state
!= IsViewable
))
514 return; /* If window is not viewable, don't change anything */
516 TSXSetInputFocus( display
, win
, RevertToParent
, CurrentTime
);
517 if (COLOR_GetSystemPaletteFlags() & COLOR_PRIVATE
)
518 TSXInstallColormap( display
, X11DRV_COLOR_GetColormap() );
523 /*****************************************************************
524 * X11DRV_WND_PreSizeMove
526 void X11DRV_WND_PreSizeMove(WND
*wndPtr
)
528 if (!(wndPtr
->dwStyle
& WS_CHILD
) &&
529 (X11DRV_WND_GetXRootWindow(wndPtr
) == DefaultRootWindow(display
)))
530 TSXGrabServer( display
);
533 /*****************************************************************
534 * X11DRV_WND_PostSizeMove
536 void X11DRV_WND_PostSizeMove(WND
*wndPtr
)
538 if (!(wndPtr
->dwStyle
& WS_CHILD
) &&
539 (X11DRV_GetXRootWindow(wndPtr
) == DefaultRootWindow(display
)))
540 TSXUngrabServer( display
);
544 /*****************************************************************
545 * X11DRV_WND_ScrollWindow
547 void X11DRV_WND_ScrollWindow(
548 WND
*wndPtr
, DC
*dcPtr
, INT32 dx
, INT32 dy
,
549 const RECT32
*clipRect
, BOOL32 bUpdate
)
551 X11DRV_PDEVICE
*physDev
= (X11DRV_PDEVICE
*)dcPtr
->physDev
;
554 if( dx
> 0 ) dst
.x
= (src
.x
= dcPtr
->w
.DCOrgX
+ clipRect
->left
) + dx
;
555 else src
.x
= (dst
.x
= dcPtr
->w
.DCOrgX
+ clipRect
->left
) - dx
;
557 if( dy
> 0 ) dst
.y
= (src
.y
= dcPtr
->w
.DCOrgY
+ clipRect
->top
) + dy
;
558 else src
.y
= (dst
.y
= dcPtr
->w
.DCOrgY
+ clipRect
->top
) - dy
;
561 if ((clipRect
->right
- clipRect
->left
> abs(dx
)) &&
562 (clipRect
->bottom
- clipRect
->top
> abs(dy
)))
564 if (bUpdate
) /* handles non-Wine windows hanging over the scrolled area */
565 TSXSetGraphicsExposures( display
, physDev
->gc
, True
);
566 TSXSetFunction( display
, physDev
->gc
, GXcopy
);
567 TSXCopyArea( display
, physDev
->drawable
, physDev
->drawable
,
568 physDev
->gc
, src
.x
, src
.y
,
569 clipRect
->right
- clipRect
->left
- abs(dx
),
570 clipRect
->bottom
- clipRect
->top
- abs(dy
),
573 TSXSetGraphicsExposures( display
, physDev
->gc
, False
);
577 /***********************************************************************
578 * X11DRV_WND_SetDrawable
580 * Set the drawable, origin and dimensions for the DC associated to
583 void X11DRV_WND_SetDrawable(WND
*wndPtr
, DC
*dc
, WORD flags
, BOOL32 bSetClipOrigin
)
585 X11DRV_PDEVICE
*physDev
= (X11DRV_PDEVICE
*)dc
->physDev
;
587 if (!wndPtr
) /* Get a DC for the whole screen */
591 physDev
->drawable
= X11DRV_WND_GetXRootWindow(wndPtr
);
592 TSXSetSubwindowMode( display
, physDev
->gc
, IncludeInferiors
);
596 if (flags
& DCX_WINDOW
)
598 dc
->w
.DCOrgX
= wndPtr
->rectWindow
.left
;
599 dc
->w
.DCOrgY
= wndPtr
->rectWindow
.top
;
603 dc
->w
.DCOrgX
= wndPtr
->rectClient
.left
;
604 dc
->w
.DCOrgY
= wndPtr
->rectClient
.top
;
606 while (!X11DRV_WND_GetXWindow(wndPtr
))
608 wndPtr
= wndPtr
->parent
;
609 dc
->w
.DCOrgX
+= wndPtr
->rectClient
.left
;
610 dc
->w
.DCOrgY
+= wndPtr
->rectClient
.top
;
612 dc
->w
.DCOrgX
-= wndPtr
->rectWindow
.left
;
613 dc
->w
.DCOrgY
-= wndPtr
->rectWindow
.top
;
614 physDev
->drawable
= X11DRV_WND_GetXWindow(wndPtr
);
617 /* This is needed when we reuse a cached DC because
618 * SetDCState() called by ReleaseDC() screws up DC
619 * origins for child windows.
623 TSXSetClipOrigin( display
, physDev
->gc
, dc
->w
.DCOrgX
, dc
->w
.DCOrgY
);
628 /***********************************************************************
629 * X11DRV_WND_IsSelfClipping
631 BOOL32
X11DRV_WND_IsSelfClipping(WND
*wndPtr
)
633 if( X11DRV_WND_GetXWindow(wndPtr
) )
634 return TRUE
; /* X itself will do the clipping */
639 #endif /* !defined(X_DISPLAY_MISSING) */