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 /* X context to associate a hwnd to an X window */
48 XContext winContext
= 0;
50 Atom wmProtocols
= None
;
51 Atom wmDeleteWindow
= None
;
52 Atom dndProtocol
= None
;
53 Atom dndSelection
= None
;
54 Atom wmChangeState
= None
;
56 Atom kwmDockWindow
= None
;
58 /***********************************************************************
59 * X11DRV_WND_GetXWindow
61 * Return the X window associated to a window.
63 Window
X11DRV_WND_GetXWindow(WND
*wndPtr
)
65 return wndPtr
&& wndPtr
->pDriverData
?
66 ((X11DRV_WND_DATA
*) wndPtr
->pDriverData
)->window
: 0;
69 /***********************************************************************
70 * X11DRV_WND_FindXWindow
72 * Return the the first X window associated to a window chain.
74 Window
X11DRV_WND_FindXWindow(WND
*wndPtr
)
77 !((X11DRV_WND_DATA
*) wndPtr
->pDriverData
)->window
)
78 wndPtr
= wndPtr
->parent
;
80 ((X11DRV_WND_DATA
*) wndPtr
->pDriverData
)->window
: 0;
83 /***********************************************************************
84 * X11DRV_WND_RegisterWindow
86 * Associate an X window to a HWND.
88 static void X11DRV_WND_RegisterWindow(WND
*wndPtr
)
90 TSXSetWMProtocols( display
, X11DRV_WND_GetXWindow(wndPtr
), &wmDeleteWindow
, 1 );
92 if (!winContext
) winContext
= TSXUniqueContext();
93 TSXSaveContext( display
, X11DRV_WND_GetXWindow(wndPtr
),
94 winContext
, (char *) wndPtr
->hwndSelf
);
97 /**********************************************************************
98 * X11DRV_WND_Initialize
100 void X11DRV_WND_Initialize(WND
*wndPtr
)
102 X11DRV_WND_DATA
*pWndDriverData
=
103 (X11DRV_WND_DATA
*) HeapAlloc(SystemHeap
, 0, sizeof(X11DRV_WND_DATA
));
105 wndPtr
->pDriverData
= (void *) pWndDriverData
;
107 pWndDriverData
->window
= 0;
110 /**********************************************************************
111 * X11DRV_WND_Finalize
113 void X11DRV_WND_Finalize(WND
*wndPtr
)
115 X11DRV_WND_DATA
*pWndDriverData
=
116 (X11DRV_WND_DATA
*) wndPtr
->pDriverData
;
118 if (!wndPtr
->pDriverData
) {
119 ERR("Trying to destroy window again. Not good.\n");
122 if(pWndDriverData
->window
)
125 "WND destroyed without destroying "
126 "the associated X Window (%ld)\n",
127 pWndDriverData
->window
130 HeapFree(SystemHeap
, 0, wndPtr
->pDriverData
);
131 wndPtr
->pDriverData
= NULL
;
134 /**********************************************************************
135 * X11DRV_WND_CreateDesktopWindow
137 BOOL
X11DRV_WND_CreateDesktopWindow(WND
*wndPtr
, CLASS
*classPtr
, BOOL bUnicode
)
139 if (wmProtocols
== None
)
140 wmProtocols
= TSXInternAtom( display
, "WM_PROTOCOLS", True
);
141 if (wmDeleteWindow
== None
)
142 wmDeleteWindow
= TSXInternAtom( display
, "WM_DELETE_WINDOW", True
);
143 if( dndProtocol
== None
)
144 dndProtocol
= TSXInternAtom( display
, "DndProtocol" , False
);
145 if( dndSelection
== None
)
146 dndSelection
= TSXInternAtom( display
, "DndSelection" , False
);
147 if( wmChangeState
== None
)
148 wmChangeState
= TSXInternAtom (display
, "WM_CHANGE_STATE", False
);
149 if (kwmDockWindow
== None
)
150 kwmDockWindow
= TSXInternAtom( display
, "KWM_DOCKWINDOW", False
);
152 ((X11DRV_WND_DATA
*) wndPtr
->pDriverData
)->window
= X11DRV_GetXRootWindow();
153 X11DRV_WND_RegisterWindow( wndPtr
);
158 /**********************************************************************
159 * X11DRV_WND_IconChanged
161 * hIcon or hIconSm has changed (or is being initialised for the
162 * first time). Complete the X11 driver-specific initialisation.
164 * This is not entirely correct, may need to create
165 * an icon window and set the pixmap as a background
167 static void X11DRV_WND_IconChanged(WND
*wndPtr
)
170 HICON16 hIcon
= NC_IconForWindow(wndPtr
);
172 if( ((X11DRV_WND_DATA
*) wndPtr
->pDriverData
)->hWMIconBitmap
)
173 DeleteObject( ((X11DRV_WND_DATA
*) wndPtr
->pDriverData
)->hWMIconBitmap
);
175 if( ((X11DRV_WND_DATA
*) wndPtr
->pDriverData
)->hWMIconMask
)
176 DeleteObject( ((X11DRV_WND_DATA
*) wndPtr
->pDriverData
)->hWMIconMask
);
180 ((X11DRV_WND_DATA
*) wndPtr
->pDriverData
)->hWMIconBitmap
= 0;
181 ((X11DRV_WND_DATA
*) wndPtr
->pDriverData
)->hWMIconMask
= 0;
191 GetIconInfo(hIcon
, &ii
);
193 X11DRV_CreateBitmap(ii
.hbmMask
);
194 X11DRV_CreateBitmap(ii
.hbmColor
);
196 GetObjectA(ii
.hbmMask
, sizeof(bmMask
), &bmMask
);
199 rcMask
.right
= bmMask
.bmWidth
;
200 rcMask
.bottom
= bmMask
.bmHeight
;
202 hDC
= CreateCompatibleDC(0);
203 hbmOrig
= SelectObject(hDC
, ii
.hbmMask
);
204 InvertRect(hDC
, &rcMask
);
205 SelectObject(hDC
, hbmOrig
);
208 ((X11DRV_WND_DATA
*) wndPtr
->pDriverData
)->hWMIconBitmap
= ii
.hbmColor
;
209 ((X11DRV_WND_DATA
*) wndPtr
->pDriverData
)->hWMIconMask
= ii
.hbmMask
;
214 static void X11DRV_WND_SetIconHints(WND
*wndPtr
, XWMHints
*hints
)
216 if (((X11DRV_WND_DATA
*) wndPtr
->pDriverData
)->hWMIconBitmap
)
219 = X11DRV_BITMAP_Pixmap(((X11DRV_WND_DATA
*) wndPtr
->pDriverData
)->hWMIconBitmap
);
220 hints
->flags
|= IconPixmapHint
;
223 hints
->flags
&= ~IconPixmapHint
;
225 if (((X11DRV_WND_DATA
*) wndPtr
->pDriverData
)->hWMIconMask
)
228 = X11DRV_BITMAP_Pixmap(((X11DRV_WND_DATA
*) wndPtr
->pDriverData
)->hWMIconMask
);
229 hints
->flags
|= IconMaskHint
;
232 hints
->flags
&= ~IconMaskHint
;
235 /**********************************************************************
236 * X11DRV_WND_UpdateIconHints
238 * hIcon or hIconSm has changed (or is being initialised for the
239 * first time). Complete the X11 driver-specific initialisation
240 * and set the window hints.
242 * This is not entirely correct, may need to create
243 * an icon window and set the pixmap as a background
245 static void X11DRV_WND_UpdateIconHints(WND
*wndPtr
)
249 X11DRV_WND_IconChanged(wndPtr
);
251 wm_hints
= TSXGetWMHints( display
, X11DRV_WND_GetXWindow(wndPtr
) );
252 if (!wm_hints
) wm_hints
= TSXAllocWMHints();
255 X11DRV_WND_SetIconHints(wndPtr
, wm_hints
);
256 TSXSetWMHints( display
, X11DRV_WND_GetXWindow(wndPtr
), wm_hints
);
262 /**********************************************************************
263 * X11DRV_WND_CreateWindow
265 BOOL
X11DRV_WND_CreateWindow(WND
*wndPtr
, CLASS
*classPtr
, CREATESTRUCTA
*cs
, BOOL bUnicode
)
267 /* Create the X window (only for top-level windows, and then only */
268 /* when there's no desktop window) */
270 if ((X11DRV_GetXRootWindow() == DefaultRootWindow(display
))
271 && (wndPtr
->parent
->hwndSelf
== GetDesktopWindow()))
275 XSetWindowAttributes win_attr
;
277 /* Create "managed" windows only if a title bar or resizable */
278 /* frame is required. */
279 if (WIN_WindowNeedsWMBorder(cs
->style
, cs
->dwExStyle
)) {
280 win_attr
.event_mask
= ExposureMask
| KeyPressMask
|
281 KeyReleaseMask
| PointerMotionMask
|
282 ButtonPressMask
| ButtonReleaseMask
|
283 FocusChangeMask
| StructureNotifyMask
;
284 win_attr
.override_redirect
= FALSE
;
285 wndPtr
->flags
|= WIN_MANAGED
;
287 win_attr
.event_mask
= ExposureMask
| KeyPressMask
|
288 KeyReleaseMask
| PointerMotionMask
|
289 ButtonPressMask
| ButtonReleaseMask
|
291 win_attr
.override_redirect
= TRUE
;
293 wndPtr
->flags
|= WIN_NATIVE
;
295 win_attr
.bit_gravity
= (classPtr
->style
& (CS_VREDRAW
| CS_HREDRAW
)) ? BGForget
: BGNorthWest
;
296 win_attr
.colormap
= X11DRV_PALETTE_PaletteXColormap
;
297 win_attr
.backing_store
= NotUseful
;
298 win_attr
.save_under
= ((classPtr
->style
& CS_SAVEBITS
) != 0);
299 win_attr
.cursor
= X11DRV_MOUSE_XCursor
;
301 ((X11DRV_WND_DATA
*) wndPtr
->pDriverData
)->hWMIconBitmap
= 0;
302 ((X11DRV_WND_DATA
*) wndPtr
->pDriverData
)->hWMIconMask
= 0;
303 ((X11DRV_WND_DATA
*) wndPtr
->pDriverData
)->bit_gravity
= win_attr
.bit_gravity
;
305 /* Zero-size X11 window hack. X doesn't like them, and will crash */
306 /* with a BadValue unless we do something ugly like this. */
307 /* FIXME: there must be a better way. */
308 if (cs
->cx
<= 0) cs
->cx
= 1;
309 if (cs
->cy
<= 0) cs
->cy
= 1;
312 ((X11DRV_WND_DATA
*) wndPtr
->pDriverData
)->window
=
313 TSXCreateWindow( display
, X11DRV_GetXRootWindow(),
314 cs
->x
, cs
->y
, cs
->cx
, cs
->cy
,
316 InputOutput
, CopyFromParent
,
317 CWEventMask
| CWOverrideRedirect
|
318 CWColormap
| CWCursor
| CWSaveUnder
|
319 CWBackingStore
| CWBitGravity
,
322 if(!(wGroupLeader
= X11DRV_WND_GetXWindow(wndPtr
)))
325 /* If we are the systray, we need to be managed to be noticed by KWM */
327 if (wndPtr
->dwExStyle
& WS_EX_TRAYWINDOW
)
328 X11DRV_WND_DockWindow(wndPtr
);
330 if (wndPtr
->flags
& WIN_MANAGED
)
332 XClassHint
*class_hints
= TSXAllocClassHint();
333 XSizeHints
* size_hints
= TSXAllocSizeHints();
337 class_hints
->res_name
= "wineManaged";
338 class_hints
->res_class
= "Wine";
339 TSXSetClassHint( display
, ((X11DRV_WND_DATA
*) wndPtr
->pDriverData
)->window
, class_hints
);
340 TSXFree (class_hints
);
345 size_hints
->win_gravity
= StaticGravity
;
346 size_hints
->flags
= PWinGravity
;
348 if (HAS_DLGFRAME(cs
->style
,cs
->dwExStyle
))
350 size_hints
->min_width
= size_hints
->max_width
= cs
->cx
;
351 size_hints
->min_height
= size_hints
->max_height
= cs
->cy
;
352 size_hints
->flags
|= PMinSize
| PMaxSize
;
355 TSXSetWMSizeHints( display
, X11DRV_WND_GetXWindow(wndPtr
),
356 size_hints
, XA_WM_NORMAL_HINTS
);
361 if (cs
->hwndParent
) /* Get window owner */
364 WND
*tmpWnd
= WIN_FindWndPtr(cs
->hwndParent
);
366 w
= X11DRV_WND_FindXWindow( tmpWnd
);
369 TSXSetTransientForHint( display
, X11DRV_WND_GetXWindow(wndPtr
), w
);
372 WIN_ReleaseWndPtr(tmpWnd
);
375 if ((wm_hints
= TSXAllocWMHints()))
377 wm_hints
->flags
= InputHint
| StateHint
| WindowGroupHint
;
378 wm_hints
->input
= True
;
380 if( wndPtr
->flags
& WIN_MANAGED
)
382 X11DRV_WND_IconChanged(wndPtr
);
383 X11DRV_WND_SetIconHints(wndPtr
, wm_hints
);
385 wm_hints
->initial_state
= (wndPtr
->dwStyle
& WS_MINIMIZE
)
386 ? IconicState
: NormalState
;
389 wm_hints
->initial_state
= NormalState
;
390 wm_hints
->window_group
= wGroupLeader
;
392 TSXSetWMHints( display
, X11DRV_WND_GetXWindow(wndPtr
), wm_hints
);
395 X11DRV_WND_RegisterWindow( wndPtr
);
400 /***********************************************************************
401 * X11DRV_WND_DestroyWindow
403 BOOL
X11DRV_WND_DestroyWindow(WND
*wndPtr
)
406 if ((w
= X11DRV_WND_GetXWindow(wndPtr
)))
409 TSXDeleteContext( display
, w
, winContext
);
410 TSXDestroyWindow( display
, w
);
411 while( TSXCheckWindowEvent(display
, w
, NoEventMask
, &xe
) );
413 ((X11DRV_WND_DATA
*) wndPtr
->pDriverData
)->window
= None
;
414 if( ((X11DRV_WND_DATA
*) wndPtr
->pDriverData
)->hWMIconBitmap
)
416 DeleteObject( ((X11DRV_WND_DATA
*) wndPtr
->pDriverData
)->hWMIconBitmap
);
417 ((X11DRV_WND_DATA
*) wndPtr
->pDriverData
)->hWMIconBitmap
= 0;
419 if( ((X11DRV_WND_DATA
*) wndPtr
->pDriverData
)->hWMIconMask
)
421 DeleteObject( ((X11DRV_WND_DATA
*) wndPtr
->pDriverData
)->hWMIconMask
);
422 ((X11DRV_WND_DATA
*) wndPtr
->pDriverData
)->hWMIconMask
= 0;
429 /*****************************************************************
430 * X11DRV_WND_SetParent
432 WND
*X11DRV_WND_SetParent(WND
*wndPtr
, WND
*pWndParent
)
434 WND
*pDesktop
= WIN_GetDesktop();
436 if( wndPtr
&& pWndParent
&& (wndPtr
!= pDesktop
) )
438 WND
* pWndPrev
= wndPtr
->parent
;
440 if( pWndParent
!= pWndPrev
)
442 if ( X11DRV_WND_GetXWindow(wndPtr
) )
444 /* Toplevel window needs to be reparented. Used by Tk 8.0 */
446 TSXDestroyWindow( display
, X11DRV_WND_GetXWindow(wndPtr
) );
447 ((X11DRV_WND_DATA
*) wndPtr
->pDriverData
)->window
= None
;
450 WIN_UnlinkWindow(wndPtr
->hwndSelf
);
451 wndPtr
->parent
= pWndParent
;
453 /* Create an X counterpart for reparented top-level windows
454 * when not in the desktop mode. */
456 if( pWndParent
== pDesktop
)
458 if( X11DRV_GetXRootWindow() == DefaultRootWindow(display
) )
461 cs
.lpCreateParams
= NULL
;
462 cs
.hInstance
= 0; /* not used in following call */
463 cs
.hMenu
= 0; /* not used in following call */
464 cs
.hwndParent
= pWndParent
->hwndSelf
;
465 cs
.cy
= wndPtr
->rectWindow
.bottom
- wndPtr
->rectWindow
.top
;
468 cs
.cx
= wndPtr
->rectWindow
.right
- wndPtr
->rectWindow
.left
;
471 cs
.y
= wndPtr
->rectWindow
.top
;
472 cs
.x
= wndPtr
->rectWindow
.left
;
473 cs
.style
= wndPtr
->dwStyle
;
474 cs
.lpszName
= 0; /* not used in following call */
475 cs
.lpszClass
= 0; /*not used in following call */
476 cs
.dwExStyle
= wndPtr
->dwExStyle
;
477 X11DRV_WND_CreateWindow(wndPtr
, wndPtr
->class,
481 else /* a child window */
483 if( !( wndPtr
->dwStyle
& WS_CHILD
) )
485 if( wndPtr
->wIDmenu
!= 0)
487 DestroyMenu( (HMENU
) wndPtr
->wIDmenu
);
492 WIN_LinkWindow(wndPtr
->hwndSelf
, HWND_TOP
);
494 WIN_ReleaseDesktop();
497 WIN_ReleaseDesktop();
501 /***********************************************************************
502 * X11DRV_WND_ForceWindowRaise
504 * Raise a window on top of the X stacking order, while preserving
505 * the correct Windows Z order.
507 void X11DRV_WND_ForceWindowRaise(WND
*wndPtr
)
509 XWindowChanges winChanges
;
510 WND
*wndPrev
,*pDesktop
= WIN_GetDesktop();
512 if( !wndPtr
|| !X11DRV_WND_GetXWindow(wndPtr
) || (wndPtr
->flags
& WIN_MANAGED
) )
514 WIN_ReleaseDesktop();
518 /* Raise all windows up to wndPtr according to their Z order.
519 * (it would be easier with sibling-related Below but it doesn't
520 * work very well with SGI mwm for instance)
522 winChanges
.stack_mode
= Above
;
525 if (X11DRV_WND_GetXWindow(wndPtr
))
526 TSXReconfigureWMWindow( display
, X11DRV_WND_GetXWindow(wndPtr
), 0,
527 CWStackMode
, &winChanges
);
528 wndPrev
= pDesktop
->child
;
529 if (wndPrev
== wndPtr
) break;
530 while (wndPrev
&& (wndPrev
->next
!= wndPtr
)) wndPrev
= wndPrev
->next
;
533 WIN_ReleaseDesktop();
536 /***********************************************************************
537 * X11DRV_WND_FindDesktopXWindow [Internal]
539 * Find the actual X window which needs be restacked.
540 * Used by X11DRV_WND_SetWindowPos().
542 static Window
X11DRV_WND_FindDesktopXWindow( WND
*wndPtr
)
544 if (!(wndPtr
->flags
& WIN_MANAGED
))
545 return X11DRV_WND_GetXWindow(wndPtr
);
548 Window window
, root
, parent
, *children
;
550 window
= X11DRV_WND_GetXWindow(wndPtr
);
553 TSXQueryTree( display
, window
, &root
, &parent
,
554 &children
, &nchildren
);
563 /***********************************************************************
564 * WINPOS_SetXWindowPos
566 * SetWindowPos() for an X window. Used by the real SetWindowPos().
568 void X11DRV_WND_SetWindowPos(WND
*wndPtr
, const WINDOWPOS
*winpos
, BOOL bChangePos
)
570 XWindowChanges winChanges
;
572 WND
*winposPtr
= WIN_FindWndPtr( winpos
->hwnd
);
573 if ( !winposPtr
) return;
575 if(!wndPtr
->hwndSelf
) wndPtr
= NULL
; /* FIXME: WND destroyed, shouldn't happen!!! */
577 if (!(winpos
->flags
& SWP_SHOWWINDOW
) && (winpos
->flags
& SWP_HIDEWINDOW
))
579 if(X11DRV_WND_GetXWindow(wndPtr
))
580 TSXUnmapWindow( display
, X11DRV_WND_GetXWindow(wndPtr
) );
585 if ( !(winpos
->flags
& SWP_NOSIZE
))
587 winChanges
.width
= (winpos
->cx
> 0 ) ? winpos
->cx
: 1;
588 winChanges
.height
= (winpos
->cy
> 0 ) ? winpos
->cy
: 1;
589 changeMask
|= CWWidth
| CWHeight
;
591 /* Tweak dialog window size hints */
593 if ((winposPtr
->flags
& WIN_MANAGED
) &&
594 HAS_DLGFRAME(winposPtr
->dwStyle
,winposPtr
->dwExStyle
))
596 XSizeHints
*size_hints
= TSXAllocSizeHints();
600 long supplied_return
;
602 TSXGetWMSizeHints( display
, X11DRV_WND_GetXWindow(winposPtr
), size_hints
,
603 &supplied_return
, XA_WM_NORMAL_HINTS
);
604 size_hints
->min_width
= size_hints
->max_width
= winpos
->cx
;
605 size_hints
->min_height
= size_hints
->max_height
= winpos
->cy
;
606 TSXSetWMSizeHints( display
, X11DRV_WND_GetXWindow(winposPtr
), size_hints
,
607 XA_WM_NORMAL_HINTS
);
612 if (!(winpos
->flags
& SWP_NOMOVE
))
614 winChanges
.x
= winpos
->x
;
615 winChanges
.y
= winpos
->y
;
616 changeMask
|= CWX
| CWY
;
618 if (!(winpos
->flags
& SWP_NOZORDER
))
620 winChanges
.stack_mode
= Below
;
621 changeMask
|= CWStackMode
;
623 if (winpos
->hwndInsertAfter
== HWND_TOP
) winChanges
.stack_mode
= Above
;
624 else if (winpos
->hwndInsertAfter
!= HWND_BOTTOM
)
626 WND
* insertPtr
= WIN_FindWndPtr( winpos
->hwndInsertAfter
);
629 stack
[0] = X11DRV_WND_FindDesktopXWindow( insertPtr
);
630 stack
[1] = X11DRV_WND_FindDesktopXWindow( winposPtr
);
632 /* for stupid window managers (i.e. all of them) */
634 TSXRestackWindows(display
, stack
, 2);
635 changeMask
&= ~CWStackMode
;
637 WIN_ReleaseWndPtr(insertPtr
);
640 if (changeMask
&& X11DRV_WND_GetXWindow(winposPtr
))
642 TSXReconfigureWMWindow( display
, X11DRV_WND_GetXWindow(winposPtr
), 0, changeMask
, &winChanges
);
643 if( winposPtr
->class->style
& (CS_VREDRAW
| CS_HREDRAW
) )
644 X11DRV_WND_SetHostAttr( winposPtr
, HAK_BITGRAVITY
, BGForget
);
648 if ( winpos
->flags
& SWP_SHOWWINDOW
)
650 if(X11DRV_WND_GetXWindow(wndPtr
))
651 TSXMapWindow( display
, X11DRV_WND_GetXWindow(wndPtr
) );
653 WIN_ReleaseWndPtr(winposPtr
);
656 /*****************************************************************
659 void X11DRV_WND_SetText(WND
*wndPtr
, LPCSTR text
)
661 if (!X11DRV_WND_GetXWindow(wndPtr
))
664 TSXStoreName( display
, X11DRV_WND_GetXWindow(wndPtr
), text
);
665 TSXSetIconName( display
, X11DRV_WND_GetXWindow(wndPtr
), text
);
668 /*****************************************************************
669 * X11DRV_WND_SetFocus
672 * Explicit colormap management seems to work only with OLVWM.
674 void X11DRV_WND_SetFocus(WND
*wndPtr
)
676 HWND hwnd
= wndPtr
->hwndSelf
;
677 XWindowAttributes win_attr
;
681 /* Only mess with the X focus if there's */
682 /* no desktop window and if the window is not managed by the WM. */
683 if ((X11DRV_GetXRootWindow() != DefaultRootWindow(display
))) return;
684 while (w
&& !((X11DRV_WND_DATA
*) w
->pDriverData
)->window
)
687 if (w
->flags
& WIN_MANAGED
) return;
689 if (!hwnd
) /* If setting the focus to 0, uninstall the colormap */
691 if (X11DRV_PALETTE_PaletteFlags
& X11DRV_PALETTE_PRIVATE
)
692 TSXUninstallColormap( display
, X11DRV_PALETTE_PaletteXColormap
);
696 /* Set X focus and install colormap */
698 if (!(win
= X11DRV_WND_FindXWindow(wndPtr
))) return;
699 if (!TSXGetWindowAttributes( display
, win
, &win_attr
) ||
700 (win_attr
.map_state
!= IsViewable
))
701 return; /* If window is not viewable, don't change anything */
703 TSXSetInputFocus( display
, win
, RevertToParent
, CurrentTime
);
704 if (X11DRV_PALETTE_PaletteFlags
& X11DRV_PALETTE_PRIVATE
)
705 TSXInstallColormap( display
, X11DRV_PALETTE_PaletteXColormap
);
710 /*****************************************************************
711 * X11DRV_WND_PreSizeMove
713 void X11DRV_WND_PreSizeMove(WND
*wndPtr
)
715 if (!(wndPtr
->dwStyle
& WS_CHILD
) && (X11DRV_GetXRootWindow() == DefaultRootWindow(display
)))
716 TSXGrabServer( display
);
719 /*****************************************************************
720 * X11DRV_WND_PostSizeMove
722 void X11DRV_WND_PostSizeMove(WND
*wndPtr
)
724 if (!(wndPtr
->dwStyle
& WS_CHILD
) &&
725 (X11DRV_GetXRootWindow() == DefaultRootWindow(display
)))
726 TSXUngrabServer( display
);
729 /*****************************************************************
730 * X11DRV_WND_SurfaceCopy
732 * Copies rect to (rect.left + dx, rect.top + dy).
734 void X11DRV_WND_SurfaceCopy(WND
* wndPtr
, DC
*dcPtr
, INT dx
, INT dy
,
735 const RECT
*rect
, BOOL bUpdate
)
737 X11DRV_PDEVICE
*physDev
= (X11DRV_PDEVICE
*)dcPtr
->physDev
;
740 dst
.x
= (src
.x
= dcPtr
->w
.DCOrgX
+ rect
->left
) + dx
;
741 dst
.y
= (src
.y
= dcPtr
->w
.DCOrgY
+ rect
->top
) + dy
;
743 if (bUpdate
) /* handles non-Wine windows hanging over the copied area */
744 TSXSetGraphicsExposures( display
, physDev
->gc
, True
);
745 TSXSetFunction( display
, physDev
->gc
, GXcopy
);
746 TSXCopyArea( display
, physDev
->drawable
, physDev
->drawable
,
747 physDev
->gc
, src
.x
, src
.y
,
748 rect
->right
- rect
->left
,
749 rect
->bottom
- rect
->top
,
752 TSXSetGraphicsExposures( display
, physDev
->gc
, False
);
754 if (bUpdate
) /* Make sure exposure events have been processed */
758 /***********************************************************************
759 * X11DRV_WND_SetDrawable
761 * Set the drawable, origin and dimensions for the DC associated to
764 void X11DRV_WND_SetDrawable(WND
*wndPtr
, DC
*dc
, WORD flags
, BOOL bSetClipOrigin
)
766 X11DRV_PDEVICE
*physDev
= (X11DRV_PDEVICE
*)dc
->physDev
;
767 INT dcOrgXCopy
= 0, dcOrgYCopy
= 0;
768 BOOL offsetClipRgn
= FALSE
;
770 if (!wndPtr
) /* Get a DC for the whole screen */
774 physDev
->drawable
= X11DRV_GetXRootWindow();
775 TSXSetSubwindowMode( display
, physDev
->gc
, IncludeInferiors
);
780 * This function change the coordinate system (DCOrgX,DCOrgY)
781 * values. When it moves the origin, other data like the current clipping
782 * region will not be moved to that new origin. In the case of DCs that are class
783 * or window DCs that clipping region might be a valid value from a previous use
784 * of the DC and changing the origin of the DC without moving the clip region
785 * results in a clip region that is not placed properly in the DC.
786 * This code will save the dc origin, let the SetDrawable
787 * modify the origin and reset the clipping. When the clipping is set,
788 * it is moved according to the new DC origin.
790 if ( (wndPtr
->class->style
& (CS_OWNDC
| CS_CLASSDC
)) && (dc
->w
.hClipRgn
> 0))
792 dcOrgXCopy
= dc
->w
.DCOrgX
;
793 dcOrgYCopy
= dc
->w
.DCOrgY
;
794 offsetClipRgn
= TRUE
;
797 if (flags
& DCX_WINDOW
)
799 dc
->w
.DCOrgX
= wndPtr
->rectWindow
.left
;
800 dc
->w
.DCOrgY
= wndPtr
->rectWindow
.top
;
804 dc
->w
.DCOrgX
= wndPtr
->rectClient
.left
;
805 dc
->w
.DCOrgY
= wndPtr
->rectClient
.top
;
807 while (!X11DRV_WND_GetXWindow(wndPtr
))
809 wndPtr
= wndPtr
->parent
;
810 dc
->w
.DCOrgX
+= wndPtr
->rectClient
.left
;
811 dc
->w
.DCOrgY
+= wndPtr
->rectClient
.top
;
813 dc
->w
.DCOrgX
-= wndPtr
->rectWindow
.left
;
814 dc
->w
.DCOrgY
-= wndPtr
->rectWindow
.top
;
816 /* reset the clip region, according to the new origin */
819 OffsetRgn(dc
->w
.hClipRgn
, dc
->w
.DCOrgX
- dcOrgXCopy
,dc
->w
.DCOrgY
- dcOrgYCopy
);
822 physDev
->drawable
= X11DRV_WND_GetXWindow(wndPtr
);
825 /* This is needed when we reuse a cached DC because
826 * SetDCState() called by ReleaseDC() screws up DC
827 * origins for child windows.
831 TSXSetClipOrigin( display
, physDev
->gc
, dc
->w
.DCOrgX
, dc
->w
.DCOrgY
);
836 /***********************************************************************
839 static BOOL
X11DRV_SetWMHint(Display
* display
, WND
* wndPtr
, int hint
, int val
)
841 XWMHints
* wm_hints
= TSXGetWMHints( display
, X11DRV_WND_GetXWindow(wndPtr
) );
842 if (!wm_hints
) wm_hints
= TSXAllocWMHints();
845 wm_hints
->flags
= hint
;
849 wm_hints
->input
= val
;
853 wm_hints
->initial_state
= val
;
857 wm_hints
->icon_pixmap
= (Pixmap
)val
;
861 wm_hints
->icon_window
= (Window
)val
;
865 TSXSetWMHints( display
, X11DRV_WND_GetXWindow(wndPtr
), wm_hints
);
873 /***********************************************************************
874 * X11DRV_WND_SetHostAttr
876 * This function returns TRUE if the attribute is supported and the
877 * action was successful. Otherwise it should return FALSE and Wine will try
878 * to get by without the functionality provided by the host window system.
880 BOOL
X11DRV_WND_SetHostAttr(WND
* wnd
, INT ha
, INT value
)
884 if( (w
= X11DRV_WND_GetXWindow(wnd
)) )
886 XSetWindowAttributes win_attr
;
890 case HAK_ICONICSTATE
: /* called when a window is minimized/restored */
892 if( (wnd
->flags
& WIN_MANAGED
) )
896 if( wnd
->dwStyle
& WS_VISIBLE
)
898 XClientMessageEvent ev
;
900 /* FIXME: set proper icon */
902 ev
.type
= ClientMessage
;
903 ev
.display
= display
;
904 ev
.message_type
= wmChangeState
;
906 ev
.data
.l
[0] = IconicState
;
909 if( TSXSendEvent (display
,
910 RootWindow( display
, XScreenNumberOfScreen(X11DRV_GetXScreen()) ),
911 True
, (SubstructureRedirectMask
| SubstructureNotifyMask
), (XEvent
*)&ev
))
915 while( !TSXCheckTypedWindowEvent( display
, w
, UnmapNotify
, &xe
) );
921 X11DRV_SetWMHint( display
, wnd
, StateHint
, IconicState
);
925 if( !(wnd
->flags
& WS_VISIBLE
) )
926 X11DRV_SetWMHint( display
, wnd
, StateHint
, NormalState
);
930 TSXMapWindow(display
, w
);
931 while( !TSXCheckTypedWindowEvent( display
, w
, MapNotify
, &xe
) );
938 case HAK_BITGRAVITY
: /* called when a window is resized */
940 if( ((X11DRV_WND_DATA
*) wnd
->pDriverData
)->bit_gravity
!= value
)
942 win_attr
.bit_gravity
= value
;
943 ((X11DRV_WND_DATA
*) wnd
->pDriverData
)->bit_gravity
= value
;
944 TSXChangeWindowAttributes( display
, w
, CWBitGravity
, &win_attr
);
948 case HAK_ICONS
: /* called when the icons change */
949 if ( (wnd
->flags
& WIN_MANAGED
) )
950 X11DRV_WND_UpdateIconHints(wnd
);
953 case HAK_ACCEPTFOCUS
: /* called when a window is disabled/enabled */
955 if( (wnd
->flags
& WIN_MANAGED
) )
956 return X11DRV_SetWMHint( display
, wnd
, InputHint
, value
);
962 /***********************************************************************
963 * X11DRV_WND_IsSelfClipping
965 BOOL
X11DRV_WND_IsSelfClipping(WND
*wndPtr
)
967 return X11DRV_WND_GetXWindow(wndPtr
) != None
;
970 /***********************************************************************
971 * X11DRV_WND_DockWindow
973 * Set the X Property of the window that tells the windowmanager we really
974 * want to be in the systray
976 * KDE: set "KWM_DOCKWINDOW", type "KWM_DOCKWINDOW" to 1 before a window is
979 * all others: to be added ;)
981 void X11DRV_WND_DockWindow(WND
*wndPtr
)
984 Window win
= X11DRV_WND_GetXWindow(wndPtr
);
985 if (kwmDockWindow
== None
)
986 return; /* no KDE running */
988 display
,win
,kwmDockWindow
,kwmDockWindow
,32,PropModeReplace
,(char*)&data
,1