4 * Copyright 1993, 1994, 1995, 1996 Alexandre Julliard
6 * 1995, 1996 Alex Korobka
11 #include <X11/Xatom.h>
21 #include "debugtools.h"
33 #include "wine/winuser16.h"
35 DEFAULT_DEBUG_CHANNEL(win
);
37 /* Some useful macros */
38 #define HAS_DLGFRAME(style,exStyle) \
39 ((!((style) & WS_THICKFRAME)) && (((style) & WS_DLGFRAME) || ((exStyle) & WS_EX_DLGMODALFRAME)))
41 /**********************************************************************/
43 extern Cursor X11DRV_MOUSE_XCursor
; /* Current X cursor */
44 extern BOOL
X11DRV_CreateBitmap( HBITMAP
);
45 extern Pixmap
X11DRV_BITMAP_Pixmap( HBITMAP
);
47 /**********************************************************************/
49 /* X context to associate a hwnd to an X window */
50 XContext winContext
= 0;
52 Atom wmProtocols
= None
;
53 Atom wmDeleteWindow
= None
;
54 Atom dndProtocol
= None
;
55 Atom dndSelection
= None
;
56 Atom wmChangeState
= None
;
58 Atom kwmDockWindow
= None
;
60 /***********************************************************************
61 * X11DRV_WND_GetXWindow
63 * Return the X window associated to a window.
65 Window
X11DRV_WND_GetXWindow(WND
*wndPtr
)
67 return wndPtr
&& wndPtr
->pDriverData
?
68 ((X11DRV_WND_DATA
*) wndPtr
->pDriverData
)->window
: 0;
71 /***********************************************************************
72 * X11DRV_WND_FindXWindow
74 * Return the the first X window associated to a window chain.
76 Window
X11DRV_WND_FindXWindow(WND
*wndPtr
)
79 !((X11DRV_WND_DATA
*) wndPtr
->pDriverData
)->window
)
80 wndPtr
= wndPtr
->parent
;
82 ((X11DRV_WND_DATA
*) wndPtr
->pDriverData
)->window
: 0;
85 /***********************************************************************
86 * X11DRV_WND_RegisterWindow
88 * Associate an X window to a HWND.
90 static void X11DRV_WND_RegisterWindow(WND
*wndPtr
)
92 TSXSetWMProtocols( display
, X11DRV_WND_GetXWindow(wndPtr
), &wmDeleteWindow
, 1 );
94 if (!winContext
) winContext
= TSXUniqueContext();
95 TSXSaveContext( display
, X11DRV_WND_GetXWindow(wndPtr
),
96 winContext
, (char *) wndPtr
->hwndSelf
);
99 /***********************************************************************
100 * X11DRV_WND_IsZeroSizeWnd
102 * Return TRUE if the window has a height or widht less or equal to 0
104 static BOOL
X11DRV_WND_IsZeroSizeWnd(WND
*wndPtr
)
106 if ( (wndPtr
->rectWindow
.left
>= wndPtr
->rectWindow
.right
) ||
107 (wndPtr
->rectWindow
.top
>= wndPtr
->rectWindow
.bottom
) )
113 /**********************************************************************
114 * X11DRV_WND_Initialize
116 void X11DRV_WND_Initialize(WND
*wndPtr
)
118 X11DRV_WND_DATA
*pWndDriverData
=
119 (X11DRV_WND_DATA
*) HeapAlloc(SystemHeap
, 0, sizeof(X11DRV_WND_DATA
));
121 wndPtr
->pDriverData
= (void *) pWndDriverData
;
123 pWndDriverData
->window
= 0;
126 /**********************************************************************
127 * X11DRV_WND_Finalize
129 void X11DRV_WND_Finalize(WND
*wndPtr
)
131 X11DRV_WND_DATA
*pWndDriverData
=
132 (X11DRV_WND_DATA
*) wndPtr
->pDriverData
;
134 if (!wndPtr
->pDriverData
) {
135 ERR("Trying to destroy window again. Not good.\n");
138 if(pWndDriverData
->window
)
141 "WND destroyed without destroying "
142 "the associated X Window (%ld)\n",
143 pWndDriverData
->window
146 HeapFree(SystemHeap
, 0, wndPtr
->pDriverData
);
147 wndPtr
->pDriverData
= NULL
;
150 /**********************************************************************
151 * X11DRV_WND_CreateDesktopWindow
153 BOOL
X11DRV_WND_CreateDesktopWindow(WND
*wndPtr
, CLASS
*classPtr
, BOOL bUnicode
)
155 if (wmProtocols
== None
)
156 wmProtocols
= TSXInternAtom( display
, "WM_PROTOCOLS", True
);
157 if (wmDeleteWindow
== None
)
158 wmDeleteWindow
= TSXInternAtom( display
, "WM_DELETE_WINDOW", True
);
159 if( dndProtocol
== None
)
160 dndProtocol
= TSXInternAtom( display
, "DndProtocol" , False
);
161 if( dndSelection
== None
)
162 dndSelection
= TSXInternAtom( display
, "DndSelection" , False
);
163 if( wmChangeState
== None
)
164 wmChangeState
= TSXInternAtom (display
, "WM_CHANGE_STATE", False
);
165 if (kwmDockWindow
== None
)
166 kwmDockWindow
= TSXInternAtom( display
, "KWM_DOCKWINDOW", False
);
168 ((X11DRV_WND_DATA
*) wndPtr
->pDriverData
)->window
= X11DRV_GetXRootWindow();
169 X11DRV_WND_RegisterWindow( wndPtr
);
174 /**********************************************************************
175 * X11DRV_WND_IconChanged
177 * hIcon or hIconSm has changed (or is being initialised for the
178 * first time). Complete the X11 driver-specific initialisation.
180 * This is not entirely correct, may need to create
181 * an icon window and set the pixmap as a background
183 static void X11DRV_WND_IconChanged(WND
*wndPtr
)
186 HICON16 hIcon
= NC_IconForWindow(wndPtr
);
188 if( ((X11DRV_WND_DATA
*) wndPtr
->pDriverData
)->hWMIconBitmap
)
189 DeleteObject( ((X11DRV_WND_DATA
*) wndPtr
->pDriverData
)->hWMIconBitmap
);
191 if( ((X11DRV_WND_DATA
*) wndPtr
->pDriverData
)->hWMIconMask
)
192 DeleteObject( ((X11DRV_WND_DATA
*) wndPtr
->pDriverData
)->hWMIconMask
);
196 ((X11DRV_WND_DATA
*) wndPtr
->pDriverData
)->hWMIconBitmap
= 0;
197 ((X11DRV_WND_DATA
*) wndPtr
->pDriverData
)->hWMIconMask
= 0;
207 GetIconInfo(hIcon
, &ii
);
209 X11DRV_CreateBitmap(ii
.hbmMask
);
210 X11DRV_CreateBitmap(ii
.hbmColor
);
212 GetObjectA(ii
.hbmMask
, sizeof(bmMask
), &bmMask
);
215 rcMask
.right
= bmMask
.bmWidth
;
216 rcMask
.bottom
= bmMask
.bmHeight
;
218 hDC
= CreateCompatibleDC(0);
219 hbmOrig
= SelectObject(hDC
, ii
.hbmMask
);
220 InvertRect(hDC
, &rcMask
);
221 SelectObject(hDC
, hbmOrig
);
224 ((X11DRV_WND_DATA
*) wndPtr
->pDriverData
)->hWMIconBitmap
= ii
.hbmColor
;
225 ((X11DRV_WND_DATA
*) wndPtr
->pDriverData
)->hWMIconMask
= ii
.hbmMask
;
230 static void X11DRV_WND_SetIconHints(WND
*wndPtr
, XWMHints
*hints
)
232 if (((X11DRV_WND_DATA
*) wndPtr
->pDriverData
)->hWMIconBitmap
)
235 = X11DRV_BITMAP_Pixmap(((X11DRV_WND_DATA
*) wndPtr
->pDriverData
)->hWMIconBitmap
);
236 hints
->flags
|= IconPixmapHint
;
239 hints
->flags
&= ~IconPixmapHint
;
241 if (((X11DRV_WND_DATA
*) wndPtr
->pDriverData
)->hWMIconMask
)
244 = X11DRV_BITMAP_Pixmap(((X11DRV_WND_DATA
*) wndPtr
->pDriverData
)->hWMIconMask
);
245 hints
->flags
|= IconMaskHint
;
248 hints
->flags
&= ~IconMaskHint
;
251 /**********************************************************************
252 * X11DRV_WND_UpdateIconHints
254 * hIcon or hIconSm has changed (or is being initialised for the
255 * first time). Complete the X11 driver-specific initialisation
256 * and set the window hints.
258 * This is not entirely correct, may need to create
259 * an icon window and set the pixmap as a background
261 static void X11DRV_WND_UpdateIconHints(WND
*wndPtr
)
265 X11DRV_WND_IconChanged(wndPtr
);
267 wm_hints
= TSXGetWMHints( display
, X11DRV_WND_GetXWindow(wndPtr
) );
268 if (!wm_hints
) wm_hints
= TSXAllocWMHints();
271 X11DRV_WND_SetIconHints(wndPtr
, wm_hints
);
272 TSXSetWMHints( display
, X11DRV_WND_GetXWindow(wndPtr
), wm_hints
);
278 /**********************************************************************
279 * X11DRV_WND_CreateWindow
281 BOOL
X11DRV_WND_CreateWindow(WND
*wndPtr
, CLASS
*classPtr
, CREATESTRUCTA
*cs
, BOOL bUnicode
)
283 /* Create the X window (only for top-level windows, and then only */
284 /* when there's no desktop window) */
286 if ((X11DRV_GetXRootWindow() == DefaultRootWindow(display
))
287 && (wndPtr
->parent
->hwndSelf
== GetDesktopWindow()))
291 XSetWindowAttributes win_attr
;
293 /* Create "managed" windows only if a title bar or resizable */
294 /* frame is required. */
295 if (WIN_WindowNeedsWMBorder(cs
->style
, cs
->dwExStyle
)) {
296 win_attr
.event_mask
= ExposureMask
| KeyPressMask
|
297 KeyReleaseMask
| PointerMotionMask
|
298 ButtonPressMask
| ButtonReleaseMask
|
299 FocusChangeMask
| StructureNotifyMask
;
300 win_attr
.override_redirect
= FALSE
;
301 wndPtr
->flags
|= WIN_MANAGED
;
303 win_attr
.event_mask
= ExposureMask
| KeyPressMask
|
304 KeyReleaseMask
| PointerMotionMask
|
305 ButtonPressMask
| ButtonReleaseMask
|
307 win_attr
.override_redirect
= TRUE
;
309 wndPtr
->flags
|= WIN_NATIVE
;
311 win_attr
.bit_gravity
= (classPtr
->style
& (CS_VREDRAW
| CS_HREDRAW
)) ? BGForget
: BGNorthWest
;
312 win_attr
.colormap
= X11DRV_PALETTE_PaletteXColormap
;
313 win_attr
.backing_store
= NotUseful
;
314 win_attr
.save_under
= ((classPtr
->style
& CS_SAVEBITS
) != 0);
315 win_attr
.cursor
= X11DRV_MOUSE_XCursor
;
317 ((X11DRV_WND_DATA
*) wndPtr
->pDriverData
)->hWMIconBitmap
= 0;
318 ((X11DRV_WND_DATA
*) wndPtr
->pDriverData
)->hWMIconMask
= 0;
319 ((X11DRV_WND_DATA
*) wndPtr
->pDriverData
)->bit_gravity
= win_attr
.bit_gravity
;
321 /* Zero-size X11 window hack. X doesn't like them, and will crash */
322 /* with a BadValue unless we do something ugly like this. */
323 /* Zero size window won't be mapped */
324 if (cs
->cx
<= 0) cs
->cx
= 1;
325 if (cs
->cy
<= 0) cs
->cy
= 1;
328 ((X11DRV_WND_DATA
*) wndPtr
->pDriverData
)->window
=
329 TSXCreateWindow( display
, X11DRV_GetXRootWindow(),
330 cs
->x
, cs
->y
, cs
->cx
, cs
->cy
,
332 InputOutput
, CopyFromParent
,
333 CWEventMask
| CWOverrideRedirect
|
334 CWColormap
| CWCursor
| CWSaveUnder
|
335 CWBackingStore
| CWBitGravity
,
338 if(!(wGroupLeader
= X11DRV_WND_GetXWindow(wndPtr
)))
341 /* If we are the systray, we need to be managed to be noticed by KWM */
343 if (wndPtr
->dwExStyle
& WS_EX_TRAYWINDOW
)
344 X11DRV_WND_DockWindow(wndPtr
);
346 if (wndPtr
->flags
& WIN_MANAGED
)
348 XClassHint
*class_hints
= TSXAllocClassHint();
349 XSizeHints
* size_hints
= TSXAllocSizeHints();
353 class_hints
->res_name
= "wineManaged";
354 class_hints
->res_class
= "Wine";
355 TSXSetClassHint( display
, ((X11DRV_WND_DATA
*) wndPtr
->pDriverData
)->window
, class_hints
);
356 TSXFree (class_hints
);
361 size_hints
->win_gravity
= StaticGravity
;
362 size_hints
->x
= cs
->x
;
363 size_hints
->y
= cs
->y
;
364 size_hints
->flags
= PWinGravity
|PPosition
;
366 if (HAS_DLGFRAME(cs
->style
,cs
->dwExStyle
))
368 size_hints
->min_width
= size_hints
->max_width
= cs
->cx
;
369 size_hints
->min_height
= size_hints
->max_height
= cs
->cy
;
370 size_hints
->flags
|= PMinSize
| PMaxSize
;
373 TSXSetWMSizeHints( display
, X11DRV_WND_GetXWindow(wndPtr
),
374 size_hints
, XA_WM_NORMAL_HINTS
);
379 if (cs
->hwndParent
) /* Get window owner */
382 WND
*tmpWnd
= WIN_FindWndPtr(cs
->hwndParent
);
384 w
= X11DRV_WND_FindXWindow( tmpWnd
);
387 TSXSetTransientForHint( display
, X11DRV_WND_GetXWindow(wndPtr
), w
);
390 WIN_ReleaseWndPtr(tmpWnd
);
393 if ((wm_hints
= TSXAllocWMHints()))
395 wm_hints
->flags
= InputHint
| StateHint
| WindowGroupHint
;
396 wm_hints
->input
= True
;
398 if( wndPtr
->flags
& WIN_MANAGED
)
400 X11DRV_WND_IconChanged(wndPtr
);
401 X11DRV_WND_SetIconHints(wndPtr
, wm_hints
);
403 wm_hints
->initial_state
= (wndPtr
->dwStyle
& WS_MINIMIZE
)
404 ? IconicState
: NormalState
;
407 wm_hints
->initial_state
= NormalState
;
408 wm_hints
->window_group
= wGroupLeader
;
410 TSXSetWMHints( display
, X11DRV_WND_GetXWindow(wndPtr
), wm_hints
);
413 X11DRV_WND_RegisterWindow( wndPtr
);
418 /***********************************************************************
419 * X11DRV_WND_DestroyWindow
421 BOOL
X11DRV_WND_DestroyWindow(WND
*wndPtr
)
424 if ((w
= X11DRV_WND_GetXWindow(wndPtr
)))
427 TSXDeleteContext( display
, w
, winContext
);
428 TSXDestroyWindow( display
, w
);
429 while( TSXCheckWindowEvent(display
, w
, NoEventMask
, &xe
) );
431 ((X11DRV_WND_DATA
*) wndPtr
->pDriverData
)->window
= None
;
432 if( ((X11DRV_WND_DATA
*) wndPtr
->pDriverData
)->hWMIconBitmap
)
434 DeleteObject( ((X11DRV_WND_DATA
*) wndPtr
->pDriverData
)->hWMIconBitmap
);
435 ((X11DRV_WND_DATA
*) wndPtr
->pDriverData
)->hWMIconBitmap
= 0;
437 if( ((X11DRV_WND_DATA
*) wndPtr
->pDriverData
)->hWMIconMask
)
439 DeleteObject( ((X11DRV_WND_DATA
*) wndPtr
->pDriverData
)->hWMIconMask
);
440 ((X11DRV_WND_DATA
*) wndPtr
->pDriverData
)->hWMIconMask
= 0;
447 /*****************************************************************
448 * X11DRV_WND_SetParent
450 WND
*X11DRV_WND_SetParent(WND
*wndPtr
, WND
*pWndParent
)
452 WND
*pDesktop
= WIN_GetDesktop();
454 if( wndPtr
&& pWndParent
&& (wndPtr
!= pDesktop
) )
456 WND
* pWndPrev
= wndPtr
->parent
;
458 if( pWndParent
!= pWndPrev
)
460 if ( X11DRV_WND_GetXWindow(wndPtr
) )
462 /* Toplevel window needs to be reparented. Used by Tk 8.0 */
464 TSXDestroyWindow( display
, X11DRV_WND_GetXWindow(wndPtr
) );
465 ((X11DRV_WND_DATA
*) wndPtr
->pDriverData
)->window
= None
;
468 WIN_UnlinkWindow(wndPtr
->hwndSelf
);
469 wndPtr
->parent
= pWndParent
;
471 /* Create an X counterpart for reparented top-level windows
472 * when not in the desktop mode. */
474 if( pWndParent
== pDesktop
)
476 if( X11DRV_GetXRootWindow() == DefaultRootWindow(display
) )
479 cs
.lpCreateParams
= NULL
;
480 cs
.hInstance
= 0; /* not used in following call */
481 cs
.hMenu
= 0; /* not used in following call */
482 cs
.hwndParent
= pWndParent
->hwndSelf
;
483 cs
.cy
= wndPtr
->rectWindow
.bottom
- wndPtr
->rectWindow
.top
;
486 cs
.cx
= wndPtr
->rectWindow
.right
- wndPtr
->rectWindow
.left
;
489 cs
.y
= wndPtr
->rectWindow
.top
;
490 cs
.x
= wndPtr
->rectWindow
.left
;
491 cs
.style
= wndPtr
->dwStyle
;
492 cs
.lpszName
= 0; /* not used in following call */
493 cs
.lpszClass
= 0; /*not used in following call */
494 cs
.dwExStyle
= wndPtr
->dwExStyle
;
495 X11DRV_WND_CreateWindow(wndPtr
, wndPtr
->class,
499 else /* a child window */
501 if( !( wndPtr
->dwStyle
& WS_CHILD
) )
503 if( wndPtr
->wIDmenu
!= 0)
505 DestroyMenu( (HMENU
) wndPtr
->wIDmenu
);
510 WIN_LinkWindow(wndPtr
->hwndSelf
, HWND_TOP
);
512 WIN_ReleaseDesktop();
515 WIN_ReleaseDesktop();
519 /***********************************************************************
520 * X11DRV_WND_ForceWindowRaise
522 * Raise a window on top of the X stacking order, while preserving
523 * the correct Windows Z order.
525 void X11DRV_WND_ForceWindowRaise(WND
*wndPtr
)
527 XWindowChanges winChanges
;
528 WND
*wndPrev
,*pDesktop
= WIN_GetDesktop();
530 if (X11DRV_WND_IsZeroSizeWnd(wndPtr
))
532 WIN_ReleaseDesktop();
536 if( !wndPtr
|| !X11DRV_WND_GetXWindow(wndPtr
) || (wndPtr
->flags
& WIN_MANAGED
) )
538 WIN_ReleaseDesktop();
542 /* Raise all windows up to wndPtr according to their Z order.
543 * (it would be easier with sibling-related Below but it doesn't
544 * work very well with SGI mwm for instance)
546 winChanges
.stack_mode
= Above
;
549 if ( !X11DRV_WND_IsZeroSizeWnd(wndPtr
) && X11DRV_WND_GetXWindow(wndPtr
) )
550 TSXReconfigureWMWindow( display
, X11DRV_WND_GetXWindow(wndPtr
), 0,
551 CWStackMode
, &winChanges
);
553 wndPrev
= pDesktop
->child
;
554 if (wndPrev
== wndPtr
) break;
555 while (wndPrev
&& (wndPrev
->next
!= wndPtr
)) wndPrev
= wndPrev
->next
;
559 WIN_ReleaseDesktop();
562 /***********************************************************************
563 * X11DRV_WND_FindDesktopXWindow [Internal]
565 * Find the actual X window which needs be restacked.
566 * Used by X11DRV_WND_SetWindowPos().
568 static Window
X11DRV_WND_FindDesktopXWindow( WND
*wndPtr
)
570 if (!(wndPtr
->flags
& WIN_MANAGED
))
571 return X11DRV_WND_GetXWindow(wndPtr
);
574 Window window
, root
, parent
, *children
;
576 window
= X11DRV_WND_GetXWindow(wndPtr
);
579 TSXQueryTree( display
, window
, &root
, &parent
,
580 &children
, &nchildren
);
589 /***********************************************************************
590 * WINPOS_SetXWindowPos
592 * SetWindowPos() for an X window. Used by the real SetWindowPos().
594 void X11DRV_WND_SetWindowPos(WND
*wndPtr
, const WINDOWPOS
*winpos
, BOOL bChangePos
)
596 XWindowChanges winChanges
;
598 BOOL isZeroSizeWnd
= FALSE
;
599 BOOL forceMapWindow
= FALSE
;
600 WND
*winposPtr
= WIN_FindWndPtr( winpos
->hwnd
);
601 if ( !winposPtr
) return;
603 /* find out if after this function we will end out with a zero-size window */
604 if (X11DRV_WND_IsZeroSizeWnd(winposPtr
))
606 /* if current size is 0, and no resizing */
607 if (winpos
->flags
& SWP_NOSIZE
)
608 isZeroSizeWnd
= TRUE
;
609 else if ((winpos
->cx
> 0) && (winpos
->cy
> 0))
611 /* if this function is setting a new size > 0 for the window, we
612 should map the window if WS_VISIBLE is set */
613 if ((winposPtr
->dwStyle
& WS_VISIBLE
) && !(winpos
->flags
& SWP_HIDEWINDOW
))
614 forceMapWindow
= TRUE
;
617 /* if resizing to 0 */
618 if ( !(winpos
->flags
& SWP_NOSIZE
) && ((winpos
->cx
<= 0) || (winpos
->cy
<= 0)) )
619 isZeroSizeWnd
= TRUE
;
621 if(!wndPtr
->hwndSelf
) wndPtr
= NULL
; /* FIXME: WND destroyed, shouldn't happen!!! */
623 if (!(winpos
->flags
& SWP_SHOWWINDOW
) && (winpos
->flags
& SWP_HIDEWINDOW
))
625 if(X11DRV_WND_GetXWindow(wndPtr
))
626 TSXUnmapWindow( display
, X11DRV_WND_GetXWindow(wndPtr
) );
631 if ( !(winpos
->flags
& SWP_NOSIZE
))
633 winChanges
.width
= (winpos
->cx
> 0 ) ? winpos
->cx
: 1;
634 winChanges
.height
= (winpos
->cy
> 0 ) ? winpos
->cy
: 1;
635 changeMask
|= CWWidth
| CWHeight
;
637 /* Tweak dialog window size hints */
639 if ((winposPtr
->flags
& WIN_MANAGED
) &&
640 HAS_DLGFRAME(winposPtr
->dwStyle
,winposPtr
->dwExStyle
))
642 XSizeHints
*size_hints
= TSXAllocSizeHints();
646 long supplied_return
;
648 TSXGetWMSizeHints( display
, X11DRV_WND_GetXWindow(winposPtr
), size_hints
,
649 &supplied_return
, XA_WM_NORMAL_HINTS
);
650 size_hints
->min_width
= size_hints
->max_width
= winpos
->cx
;
651 size_hints
->min_height
= size_hints
->max_height
= winpos
->cy
;
652 TSXSetWMSizeHints( display
, X11DRV_WND_GetXWindow(winposPtr
), size_hints
,
653 XA_WM_NORMAL_HINTS
);
658 if (!(winpos
->flags
& SWP_NOMOVE
))
660 winChanges
.x
= winpos
->x
;
661 winChanges
.y
= winpos
->y
;
662 changeMask
|= CWX
| CWY
;
664 if (!(winpos
->flags
& SWP_NOZORDER
) && !isZeroSizeWnd
)
666 winChanges
.stack_mode
= Below
;
667 changeMask
|= CWStackMode
;
669 if (winpos
->hwndInsertAfter
== HWND_TOP
) winChanges
.stack_mode
= Above
;
670 else if (winpos
->hwndInsertAfter
!= HWND_BOTTOM
)
672 WND
* insertPtr
= WIN_FindWndPtr( winpos
->hwndInsertAfter
);
675 stack
[0] = X11DRV_WND_FindDesktopXWindow( insertPtr
);
676 stack
[1] = X11DRV_WND_FindDesktopXWindow( winposPtr
);
678 /* for stupid window managers (i.e. all of them) */
680 if (!X11DRV_WND_IsZeroSizeWnd(insertPtr
))
682 TSXRestackWindows(display
, stack
, 2);
683 changeMask
&= ~CWStackMode
;
685 WIN_ReleaseWndPtr(insertPtr
);
688 if (changeMask
&& X11DRV_WND_GetXWindow(winposPtr
))
690 TSXReconfigureWMWindow( display
, X11DRV_WND_GetXWindow(winposPtr
), 0, changeMask
, &winChanges
);
691 if( winposPtr
->class->style
& (CS_VREDRAW
| CS_HREDRAW
) )
692 X11DRV_WND_SetHostAttr( winposPtr
, HAK_BITGRAVITY
, BGForget
);
696 /* don't map the window if it's a zero size window */
697 if ( ((winpos
->flags
& SWP_SHOWWINDOW
) && !isZeroSizeWnd
) || forceMapWindow
)
699 if(X11DRV_WND_GetXWindow(wndPtr
))
700 TSXMapWindow( display
, X11DRV_WND_GetXWindow(wndPtr
) );
702 WIN_ReleaseWndPtr(winposPtr
);
705 /*****************************************************************
708 void X11DRV_WND_SetText(WND
*wndPtr
, LPCWSTR text
)
712 static UINT text_cp
= (UINT
)-1;
715 if (!(win
= X11DRV_WND_GetXWindow(wndPtr
))) return;
717 if(text_cp
== (UINT
)-1)
719 text_cp
= PROFILE_GetWineIniInt("x11drv", "TextCP", CP_ACP
);
720 TRACE("text_cp = %u\n", text_cp
);
723 /* allocate new buffer for window text */
724 count
= WideCharToMultiByte(text_cp
, 0, text
, -1, NULL
, 0, NULL
, NULL
);
725 if (!(buffer
= HeapAlloc( GetProcessHeap(), 0, count
* sizeof(WCHAR
) )))
727 ERR("Not enough memory for window text\n");
730 WideCharToMultiByte(text_cp
, 0, text
, -1, buffer
, count
, NULL
, NULL
);
732 TSXStoreName( display
, win
, buffer
);
733 TSXSetIconName( display
, win
, buffer
);
734 HeapFree( GetProcessHeap(), 0, buffer
);
737 /*****************************************************************
738 * X11DRV_WND_SetFocus
741 * Explicit colormap management seems to work only with OLVWM.
743 void X11DRV_WND_SetFocus(WND
*wndPtr
)
745 HWND hwnd
= wndPtr
->hwndSelf
;
746 XWindowAttributes win_attr
;
750 if (X11DRV_WND_IsZeroSizeWnd(wndPtr
))
753 /* Only mess with the X focus if there's */
754 /* no desktop window and if the window is not managed by the WM. */
755 if ((X11DRV_GetXRootWindow() != DefaultRootWindow(display
))) return;
756 while (w
&& !((X11DRV_WND_DATA
*) w
->pDriverData
)->window
)
759 if (w
->flags
& WIN_MANAGED
) return;
761 if (!hwnd
) /* If setting the focus to 0, uninstall the colormap */
763 if (X11DRV_PALETTE_PaletteFlags
& X11DRV_PALETTE_PRIVATE
)
764 TSXUninstallColormap( display
, X11DRV_PALETTE_PaletteXColormap
);
768 /* Set X focus and install colormap */
770 if (!(win
= X11DRV_WND_FindXWindow(wndPtr
))) return;
771 if (!TSXGetWindowAttributes( display
, win
, &win_attr
) ||
772 (win_attr
.map_state
!= IsViewable
))
773 return; /* If window is not viewable, don't change anything */
775 TSXSetInputFocus( display
, win
, RevertToParent
, CurrentTime
);
776 if (X11DRV_PALETTE_PaletteFlags
& X11DRV_PALETTE_PRIVATE
)
777 TSXInstallColormap( display
, X11DRV_PALETTE_PaletteXColormap
);
782 /*****************************************************************
783 * X11DRV_WND_PreSizeMove
785 void X11DRV_WND_PreSizeMove(WND
*wndPtr
)
787 if (!(wndPtr
->dwStyle
& WS_CHILD
) && (X11DRV_GetXRootWindow() == DefaultRootWindow(display
)))
788 TSXGrabServer( display
);
791 /*****************************************************************
792 * X11DRV_WND_PostSizeMove
794 void X11DRV_WND_PostSizeMove(WND
*wndPtr
)
796 if (!(wndPtr
->dwStyle
& WS_CHILD
) &&
797 (X11DRV_GetXRootWindow() == DefaultRootWindow(display
)))
798 TSXUngrabServer( display
);
801 /*****************************************************************
802 * X11DRV_WND_SurfaceCopy
804 * Copies rect to (rect.left + dx, rect.top + dy).
806 void X11DRV_WND_SurfaceCopy(WND
* wndPtr
, HDC hdc
, INT dx
, INT dy
,
807 const RECT
*rect
, BOOL bUpdate
)
809 X11DRV_PDEVICE
*physDev
;
811 DC
*dcPtr
= DC_GetDCPtr( hdc
);
814 physDev
= (X11DRV_PDEVICE
*)dcPtr
->physDev
;
815 dst
.x
= (src
.x
= dcPtr
->w
.DCOrgX
+ rect
->left
) + dx
;
816 dst
.y
= (src
.y
= dcPtr
->w
.DCOrgY
+ rect
->top
) + dy
;
818 if (bUpdate
) /* handles non-Wine windows hanging over the copied area */
819 TSXSetGraphicsExposures( display
, physDev
->gc
, True
);
820 TSXSetFunction( display
, physDev
->gc
, GXcopy
);
821 TSXCopyArea( display
, physDev
->drawable
, physDev
->drawable
,
822 physDev
->gc
, src
.x
, src
.y
,
823 rect
->right
- rect
->left
,
824 rect
->bottom
- rect
->top
,
827 TSXSetGraphicsExposures( display
, physDev
->gc
, False
);
829 if (bUpdate
) /* Make sure exposure events have been processed */
831 GDI_HEAP_UNLOCK( hdc
);
834 /***********************************************************************
835 * X11DRV_WND_SetDrawable
837 * Set the drawable, origin and dimensions for the DC associated to
840 void X11DRV_WND_SetDrawable(WND
*wndPtr
, HDC hdc
, WORD flags
, BOOL bSetClipOrigin
)
842 DC
*dc
= DC_GetDCPtr( hdc
);
843 X11DRV_PDEVICE
*physDev
;
844 INT dcOrgXCopy
= 0, dcOrgYCopy
= 0;
845 BOOL offsetClipRgn
= FALSE
;
848 physDev
= (X11DRV_PDEVICE
*)dc
->physDev
;
849 if (!wndPtr
) /* Get a DC for the whole screen */
853 physDev
->drawable
= X11DRV_GetXRootWindow();
854 TSXSetSubwindowMode( display
, physDev
->gc
, IncludeInferiors
);
859 * This function change the coordinate system (DCOrgX,DCOrgY)
860 * values. When it moves the origin, other data like the current clipping
861 * region will not be moved to that new origin. In the case of DCs that are class
862 * or window DCs that clipping region might be a valid value from a previous use
863 * of the DC and changing the origin of the DC without moving the clip region
864 * results in a clip region that is not placed properly in the DC.
865 * This code will save the dc origin, let the SetDrawable
866 * modify the origin and reset the clipping. When the clipping is set,
867 * it is moved according to the new DC origin.
869 if ( (wndPtr
->class->style
& (CS_OWNDC
| CS_CLASSDC
)) && (dc
->w
.hClipRgn
> 0))
871 dcOrgXCopy
= dc
->w
.DCOrgX
;
872 dcOrgYCopy
= dc
->w
.DCOrgY
;
873 offsetClipRgn
= TRUE
;
876 if (flags
& DCX_WINDOW
)
878 dc
->w
.DCOrgX
= wndPtr
->rectWindow
.left
;
879 dc
->w
.DCOrgY
= wndPtr
->rectWindow
.top
;
883 dc
->w
.DCOrgX
= wndPtr
->rectClient
.left
;
884 dc
->w
.DCOrgY
= wndPtr
->rectClient
.top
;
886 while (!X11DRV_WND_GetXWindow(wndPtr
))
888 wndPtr
= wndPtr
->parent
;
889 dc
->w
.DCOrgX
+= wndPtr
->rectClient
.left
;
890 dc
->w
.DCOrgY
+= wndPtr
->rectClient
.top
;
892 dc
->w
.DCOrgX
-= wndPtr
->rectWindow
.left
;
893 dc
->w
.DCOrgY
-= wndPtr
->rectWindow
.top
;
895 /* reset the clip region, according to the new origin */
898 OffsetRgn(dc
->w
.hClipRgn
, dc
->w
.DCOrgX
- dcOrgXCopy
,dc
->w
.DCOrgY
- dcOrgYCopy
);
901 physDev
->drawable
= X11DRV_WND_GetXWindow(wndPtr
);
904 /* This is needed when we reuse a cached DC because
905 * SetDCState() called by ReleaseDC() screws up DC
906 * origins for child windows.
910 TSXSetClipOrigin( display
, physDev
->gc
, dc
->w
.DCOrgX
, dc
->w
.DCOrgY
);
913 GDI_HEAP_UNLOCK( hdc
);
916 /***********************************************************************
919 static BOOL
X11DRV_SetWMHint(Display
* display
, WND
* wndPtr
, int hint
, int val
)
921 XWMHints
* wm_hints
= TSXGetWMHints( display
, X11DRV_WND_GetXWindow(wndPtr
) );
922 if (!wm_hints
) wm_hints
= TSXAllocWMHints();
925 wm_hints
->flags
= hint
;
929 wm_hints
->input
= val
;
933 wm_hints
->initial_state
= val
;
937 wm_hints
->icon_pixmap
= (Pixmap
)val
;
941 wm_hints
->icon_window
= (Window
)val
;
945 TSXSetWMHints( display
, X11DRV_WND_GetXWindow(wndPtr
), wm_hints
);
953 /***********************************************************************
954 * X11DRV_WND_SetHostAttr
956 * This function returns TRUE if the attribute is supported and the
957 * action was successful. Otherwise it should return FALSE and Wine will try
958 * to get by without the functionality provided by the host window system.
960 BOOL
X11DRV_WND_SetHostAttr(WND
* wnd
, INT ha
, INT value
)
964 if( (w
= X11DRV_WND_GetXWindow(wnd
)) )
966 XSetWindowAttributes win_attr
;
970 case HAK_ICONICSTATE
: /* called when a window is minimized/restored */
972 /* don't do anything if it'a zero size window */
973 if (X11DRV_WND_IsZeroSizeWnd(wnd
))
976 if( (wnd
->flags
& WIN_MANAGED
) )
980 if( wnd
->dwStyle
& WS_VISIBLE
)
982 XClientMessageEvent ev
;
984 /* FIXME: set proper icon */
986 ev
.type
= ClientMessage
;
987 ev
.display
= display
;
988 ev
.message_type
= wmChangeState
;
990 ev
.data
.l
[0] = IconicState
;
993 if( TSXSendEvent (display
,
994 RootWindow( display
, XScreenNumberOfScreen(X11DRV_GetXScreen()) ),
995 True
, (SubstructureRedirectMask
| SubstructureNotifyMask
), (XEvent
*)&ev
))
999 while( !TSXCheckTypedWindowEvent( display
, w
, UnmapNotify
, &xe
) );
1005 X11DRV_SetWMHint( display
, wnd
, StateHint
, IconicState
);
1009 if( !(wnd
->flags
& WS_VISIBLE
) )
1010 X11DRV_SetWMHint( display
, wnd
, StateHint
, NormalState
);
1014 TSXMapWindow(display
, w
);
1015 while( !TSXCheckTypedWindowEvent( display
, w
, MapNotify
, &xe
) );
1022 case HAK_BITGRAVITY
: /* called when a window is resized */
1024 if( ((X11DRV_WND_DATA
*) wnd
->pDriverData
)->bit_gravity
!= value
)
1026 win_attr
.bit_gravity
= value
;
1027 ((X11DRV_WND_DATA
*) wnd
->pDriverData
)->bit_gravity
= value
;
1028 TSXChangeWindowAttributes( display
, w
, CWBitGravity
, &win_attr
);
1032 case HAK_ICONS
: /* called when the icons change */
1033 if ( (wnd
->flags
& WIN_MANAGED
) )
1034 X11DRV_WND_UpdateIconHints(wnd
);
1037 case HAK_ACCEPTFOCUS
: /* called when a window is disabled/enabled */
1039 if( (wnd
->flags
& WIN_MANAGED
) )
1040 return X11DRV_SetWMHint( display
, wnd
, InputHint
, value
);
1046 /***********************************************************************
1047 * X11DRV_WND_IsSelfClipping
1049 BOOL
X11DRV_WND_IsSelfClipping(WND
*wndPtr
)
1051 return X11DRV_WND_GetXWindow(wndPtr
) != None
;
1054 /***********************************************************************
1055 * X11DRV_WND_DockWindow
1057 * Set the X Property of the window that tells the windowmanager we really
1058 * want to be in the systray
1060 * KDE: set "KWM_DOCKWINDOW", type "KWM_DOCKWINDOW" to 1 before a window is
1063 * all others: to be added ;)
1065 void X11DRV_WND_DockWindow(WND
*wndPtr
)
1068 Window win
= X11DRV_WND_GetXWindow(wndPtr
);
1069 if (kwmDockWindow
== None
)
1070 return; /* no KDE running */
1072 display
,win
,kwmDockWindow
,kwmDockWindow
,32,PropModeReplace
,(char*)&data
,1
1077 /***********************************************************************
1078 * X11DRV_WND_SetWindowRgn
1080 * Assign specified region to window (for non-rectangular windows)
1082 void X11DRV_WND_SetWindowRgn(WND
*wndPtr
, HRGN hrgnWnd
)
1084 #ifdef HAVE_LIBXSHAPE
1085 Window win
= X11DRV_WND_GetXWindow(wndPtr
);
1091 TSXShapeCombineMask( display
, win
, ShapeBounding
, 0, 0, None
, ShapeSet
);
1097 DWORD dwBufferSize
= GetRegionData(hrgnWnd
, 0, NULL
);
1098 PRGNDATA pRegionData
= HeapAlloc(GetProcessHeap(), 0, dwBufferSize
);
1099 if (!pRegionData
) return;
1101 GetRegionData(hrgnWnd
, dwBufferSize
, pRegionData
);
1102 size
= pRegionData
->rdh
.nCount
;
1103 /* convert region's "Windows rectangles" to XRectangles */
1104 aXRect
= HeapAlloc(GetProcessHeap(), 0, size
* sizeof(*aXRect
) );
1107 XRectangle
* pCurrRect
= aXRect
;
1108 RECT
*pRect
= (RECT
*) pRegionData
->Buffer
;
1109 for (; pRect
< ((RECT
*) pRegionData
->Buffer
) + size
; ++pRect
, ++pCurrRect
)
1111 pCurrRect
->x
= pRect
->left
;
1112 pCurrRect
->y
= pRect
->top
;
1113 pCurrRect
->height
= pRect
->bottom
- pRect
->top
;
1114 pCurrRect
->width
= pRect
->right
- pRect
->left
;
1116 TRACE("Rectangle %04d of %04ld data: X=%04d, Y=%04d, Height=%04d, Width=%04d.\n",
1117 pRect
- (RECT
*) pRegionData
->Buffer
,
1125 /* shape = non-rectangular windows (X11/extensions) */
1126 TSXShapeCombineRectangles( display
, win
, ShapeBounding
,
1128 pCurrRect
- aXRect
, ShapeSet
, YXBanded
);
1129 HeapFree(GetProcessHeap(), 0, aXRect
);
1131 HeapFree(GetProcessHeap(), 0, pRegionData
);
1133 #endif /* HAVE_LIBXSHAPE */