4 * Copyright 1993, 1994, 1995, 1996 Alexandre Julliard
6 * 1995, 1996 Alex Korobka
11 #include <X11/Xatom.h>
21 #include "debugtools.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
,
51 X11DRV_WND_CreateDesktopWindow
,
52 X11DRV_WND_CreateWindow
,
53 X11DRV_WND_DestroyWindow
,
55 X11DRV_WND_ForceWindowRaise
,
56 X11DRV_WND_SetWindowPos
,
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
)
101 !((X11DRV_WND_DATA
*) wndPtr
->pDriverData
)->window
)
102 wndPtr
= wndPtr
->parent
;
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
) )
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");
160 if(pWndDriverData
->window
)
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
);
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
);
222 ((X11DRV_WND_DATA
*) wndPtr
->pDriverData
)->hWMIconBitmap
= 0;
223 ((X11DRV_WND_DATA
*) wndPtr
->pDriverData
)->hWMIconMask
= 0;
233 GetIconInfo(hIcon
, &ii
);
235 X11DRV_CreateBitmap(ii
.hbmMask
);
236 X11DRV_CreateBitmap(ii
.hbmColor
);
238 GetObjectA(ii
.hbmMask
, sizeof(bmMask
), &bmMask
);
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
);
250 ((X11DRV_WND_DATA
*) wndPtr
->pDriverData
)->hWMIconBitmap
= ii
.hbmColor
;
251 ((X11DRV_WND_DATA
*) wndPtr
->pDriverData
)->hWMIconMask
= ii
.hbmMask
;
256 static void X11DRV_WND_SetIconHints(WND
*wndPtr
, XWMHints
*hints
)
258 if (((X11DRV_WND_DATA
*) wndPtr
->pDriverData
)->hWMIconBitmap
)
261 = X11DRV_BITMAP_Pixmap(((X11DRV_WND_DATA
*) wndPtr
->pDriverData
)->hWMIconBitmap
);
262 hints
->flags
|= IconPixmapHint
;
265 hints
->flags
&= ~IconPixmapHint
;
267 if (((X11DRV_WND_DATA
*) wndPtr
->pDriverData
)->hWMIconMask
)
270 = X11DRV_BITMAP_Pixmap(((X11DRV_WND_DATA
*) wndPtr
->pDriverData
)->hWMIconMask
);
271 hints
->flags
|= IconMaskHint
;
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
)
291 X11DRV_WND_IconChanged(wndPtr
);
293 wm_hints
= TSXGetWMHints( display
, X11DRV_WND_GetXWindow(wndPtr
) );
294 if (!wm_hints
) wm_hints
= TSXAllocWMHints();
297 X11DRV_WND_SetIconHints(wndPtr
, wm_hints
);
298 TSXSetWMHints( display
, X11DRV_WND_GetXWindow(wndPtr
), 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()))
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
;
329 win_attr
.event_mask
= ExposureMask
| KeyPressMask
|
330 KeyReleaseMask
| PointerMotionMask
|
331 ButtonPressMask
| ButtonReleaseMask
|
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
,
358 InputOutput
, CopyFromParent
,
359 CWEventMask
| CWOverrideRedirect
|
360 CWColormap
| CWCursor
| CWSaveUnder
|
361 CWBackingStore
| CWBitGravity
,
364 if(!(wGroupLeader
= X11DRV_WND_GetXWindow(wndPtr
)))
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();
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
);
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
);
405 if (cs
->hwndParent
) /* Get window owner */
408 WND
*tmpWnd
= WIN_FindWndPtr(cs
->hwndParent
);
410 w
= X11DRV_WND_FindXWindow( tmpWnd
);
413 TSXSetTransientForHint( display
, X11DRV_WND_GetXWindow(wndPtr
), 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
;
433 wm_hints
->initial_state
= NormalState
;
434 wm_hints
->window_group
= wGroupLeader
;
436 TSXSetWMHints( display
, X11DRV_WND_GetXWindow(wndPtr
), wm_hints
);
439 X11DRV_WND_RegisterWindow( wndPtr
);
444 /***********************************************************************
445 * X11DRV_WND_DestroyWindow
447 BOOL
X11DRV_WND_DestroyWindow(WND
*wndPtr
)
450 if ((w
= X11DRV_WND_GetXWindow(wndPtr
)))
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;
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
) )
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
;
512 cs
.cx
= wndPtr
->rectWindow
.right
- wndPtr
->rectWindow
.left
;
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
);
535 WIN_LinkWindow(wndPtr
->hwndSelf
, HWND_TOP
);
537 WIN_ReleaseDesktop();
540 WIN_ReleaseDesktop();
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();
561 if( !wndPtr
|| !X11DRV_WND_GetXWindow(wndPtr
) || (wndPtr
->dwExStyle
& WS_EX_MANAGED
) )
563 WIN_ReleaseDesktop();
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
;
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
;
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
);
599 Window window
, root
, parent
, *children
;
601 window
= X11DRV_WND_GetXWindow(wndPtr
);
604 TSXQueryTree( display
, window
, &root
, &parent
,
605 &children
, &nchildren
);
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
;
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
) );
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();
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
);
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
);
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
;
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
;
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
;
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 /*****************************************************************
776 void X11DRV_WND_SetText(WND
*wndPtr
, LPCWSTR text
)
780 static UINT text_cp
= (UINT
)-1;
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");
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
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
;
818 if (X11DRV_WND_IsZeroSizeWnd(wndPtr
))
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
)
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
);
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
);
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
;
880 DC
*dcPtr
= DC_GetDCPtr( hdc
);
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
,
896 TSXSetGraphicsExposures( display
, physDev
->gc
, False
);
897 GDI_ReleaseObj( hdc
);
899 if (bUpdate
) /* Make sure exposure events have been processed */
903 /***********************************************************************
904 * X11DRV_WND_SetDrawable
906 * Set the drawable, origin and dimensions for the DC associated to
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
;
917 physDev
= (X11DRV_PDEVICE
*)dc
->physDev
;
918 if (!wndPtr
) /* Get a DC for the whole screen */
922 physDev
->drawable
= X11DRV_GetXRootWindow();
923 TSXSetSubwindowMode( display
, physDev
->gc
, IncludeInferiors
);
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
;
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 */
967 OffsetRgn(dc
->hClipRgn
, dc
->DCOrgX
- dcOrgXCopy
,dc
->DCOrgY
- dcOrgYCopy
);
970 physDev
->drawable
= X11DRV_WND_GetXWindow(wndPtr
);
973 /* This is needed when we reuse a cached DC because
974 * SetDCState() called by ReleaseDC() screws up DC
975 * origins for child windows.
979 TSXSetClipOrigin( display
, physDev
->gc
, dc
->DCOrgX
, dc
->DCOrgY
);
982 GDI_ReleaseObj( hdc
);
985 /***********************************************************************
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();
994 wm_hints
->flags
= hint
;
998 wm_hints
->input
= val
;
1002 wm_hints
->initial_state
= val
;
1005 case IconPixmapHint
:
1006 wm_hints
->icon_pixmap
= (Pixmap
)val
;
1009 case IconWindowHint
:
1010 wm_hints
->icon_window
= (Window
)val
;
1014 TSXSetWMHints( display
, X11DRV_WND_GetXWindow(wndPtr
), wm_hints
);
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
)
1033 if( (w
= X11DRV_WND_GetXWindow(wnd
)) )
1035 XSetWindowAttributes win_attr
;
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
))
1045 if( (wnd
->dwExStyle
& WS_EX_MANAGED
) )
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
;
1059 ev
.data
.l
[0] = IconicState
;
1062 if( TSXSendEvent (display
,
1063 RootWindow( display
, XScreenNumberOfScreen(X11DRV_GetXScreen()) ),
1064 True
, (SubstructureRedirectMask
| SubstructureNotifyMask
), (XEvent
*)&ev
))
1068 while( !TSXCheckTypedWindowEvent( display
, w
, UnmapNotify
, &xe
) );
1074 X11DRV_SetWMHint( display
, wnd
, StateHint
, IconicState
);
1078 if( !(wnd
->flags
& WS_VISIBLE
) )
1079 X11DRV_SetWMHint( display
, wnd
, StateHint
, NormalState
);
1083 TSXMapWindow(display
, w
);
1084 while( !TSXCheckTypedWindowEvent( display
, w
, MapNotify
, &xe
) );
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
);
1101 case HAK_ICONS
: /* called when the icons change */
1102 if ( (wnd
->dwExStyle
& WS_EX_MANAGED
) )
1103 X11DRV_WND_UpdateIconHints(wnd
);
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
);
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
1132 * all others: to be added ;)
1134 void X11DRV_WND_DockWindow(WND
*wndPtr
)
1137 Window win
= X11DRV_WND_GetXWindow(wndPtr
);
1138 if (kwmDockWindow
!= None
) {
1140 display
,win
,kwmDockWindow
,kwmDockWindow
,32,PropModeReplace
,(char*)&data
,1
1143 if (_kde_net_wm_system_tray_window_for
!= None
) {
1147 _kde_net_wm_system_tray_window_for
,
1155 if (_net_kde_system_tray_window_for
!= None
) {
1159 _net_kde_system_tray_window_for
,
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
);
1185 TSXShapeCombineMask( display
, win
, ShapeBounding
, 0, 0, None
, ShapeSet
);
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
) );
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
,
1219 /* shape = non-rectangular windows (X11/extensions) */
1220 TSXShapeCombineRectangles( display
, win
, ShapeBounding
,
1222 pCurrRect
- aXRect
, ShapeSet
, YXBanded
);
1223 HeapFree(GetProcessHeap(), 0, aXRect
);
1225 HeapFree(GetProcessHeap(), 0, pRegionData
);
1227 #endif /* HAVE_LIBXSHAPE */