Moved zero-sized window hack to x11drv.
[wine.git] / windows / x11drv / wnd.c
bloba8ae0e5813c3c7d48436ba482d3a0614e637d4b6
1 /*
2 * X11 windows driver
4 * Copyright 1993, 1994, 1995, 1996 Alexandre Julliard
5 * 1993 David Metcalfe
6 * 1995, 1996 Alex Korobka
7 */
9 #include "config.h"
11 #include <X11/Xatom.h>
13 #include "ts_xlib.h"
14 #include "ts_xutil.h"
16 #include <stdlib.h>
17 #include <string.h>
19 #include "bitmap.h"
20 #include "color.h"
21 #include "debugtools.h"
22 #include "dce.h"
23 #include "options.h"
24 #include "message.h"
25 #include "heap.h"
26 #include "win.h"
27 #include "windef.h"
28 #include "class.h"
29 #include "x11drv.h"
30 #include "wingdi.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)
76 while (wndPtr &&
77 !((X11DRV_WND_DATA *) wndPtr->pDriverData)->window)
78 wndPtr = wndPtr->parent;
79 return wndPtr ?
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");
120 return;
122 if(pWndDriverData->window)
124 ERR(
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 );
155 return TRUE;
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);
178 if (!hIcon)
180 ((X11DRV_WND_DATA *) wndPtr->pDriverData)->hWMIconBitmap= 0;
181 ((X11DRV_WND_DATA *) wndPtr->pDriverData)->hWMIconMask= 0;
183 else
185 HBITMAP hbmOrig;
186 RECT rcMask;
187 BITMAP bmMask;
188 ICONINFO ii;
189 HDC hDC;
191 GetIconInfo(hIcon, &ii);
193 X11DRV_CreateBitmap(ii.hbmMask);
194 X11DRV_CreateBitmap(ii.hbmColor);
196 GetObjectA(ii.hbmMask, sizeof(bmMask), &bmMask);
197 rcMask.top = 0;
198 rcMask.left = 0;
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);
206 DeleteDC(hDC);
208 ((X11DRV_WND_DATA *) wndPtr->pDriverData)->hWMIconBitmap = ii.hbmColor;
209 ((X11DRV_WND_DATA *) wndPtr->pDriverData)->hWMIconMask= ii.hbmMask;
211 return;
214 static void X11DRV_WND_SetIconHints(WND *wndPtr, XWMHints *hints)
216 if (((X11DRV_WND_DATA *) wndPtr->pDriverData)->hWMIconBitmap)
218 hints->icon_pixmap
219 = X11DRV_BITMAP_Pixmap(((X11DRV_WND_DATA *) wndPtr->pDriverData)->hWMIconBitmap);
220 hints->flags |= IconPixmapHint;
222 else
223 hints->flags &= ~IconPixmapHint;
225 if (((X11DRV_WND_DATA *) wndPtr->pDriverData)->hWMIconMask)
227 hints->icon_mask
228 = X11DRV_BITMAP_Pixmap(((X11DRV_WND_DATA *) wndPtr->pDriverData)->hWMIconMask);
229 hints->flags |= IconMaskHint;
231 else
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)
247 XWMHints* wm_hints;
249 X11DRV_WND_IconChanged(wndPtr);
251 wm_hints = TSXGetWMHints( display, X11DRV_WND_GetXWindow(wndPtr) );
252 if (!wm_hints) wm_hints = TSXAllocWMHints();
253 if (wm_hints)
255 X11DRV_WND_SetIconHints(wndPtr, wm_hints);
256 TSXSetWMHints( display, X11DRV_WND_GetXWindow(wndPtr), wm_hints );
257 TSXFree( 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()))
273 Window wGroupLeader;
274 XWMHints* wm_hints;
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;
286 } else {
287 win_attr.event_mask = ExposureMask | KeyPressMask |
288 KeyReleaseMask | PointerMotionMask |
289 ButtonPressMask | ButtonReleaseMask |
290 FocusChangeMask;
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;
310 /* EMXIF */
312 ((X11DRV_WND_DATA *) wndPtr->pDriverData)->window =
313 TSXCreateWindow( display, X11DRV_GetXRootWindow(),
314 cs->x, cs->y, cs->cx, cs->cy,
315 0, CopyFromParent,
316 InputOutput, CopyFromParent,
317 CWEventMask | CWOverrideRedirect |
318 CWColormap | CWCursor | CWSaveUnder |
319 CWBackingStore | CWBitGravity,
320 &win_attr );
322 if(!(wGroupLeader = X11DRV_WND_GetXWindow(wndPtr)))
323 return FALSE;
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();
335 if (class_hints)
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);
343 if (size_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 );
357 TSXFree(size_hints);
361 if (cs->hwndParent) /* Get window owner */
363 Window w;
364 WND *tmpWnd = WIN_FindWndPtr(cs->hwndParent);
366 w = X11DRV_WND_FindXWindow( tmpWnd );
367 if (w != None)
369 TSXSetTransientForHint( display, X11DRV_WND_GetXWindow(wndPtr), w );
370 wGroupLeader = 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;
388 else
389 wm_hints->initial_state = NormalState;
390 wm_hints->window_group = wGroupLeader;
392 TSXSetWMHints( display, X11DRV_WND_GetXWindow(wndPtr), wm_hints );
393 TSXFree(wm_hints);
395 X11DRV_WND_RegisterWindow( wndPtr );
397 return TRUE;
400 /***********************************************************************
401 * X11DRV_WND_DestroyWindow
403 BOOL X11DRV_WND_DestroyWindow(WND *wndPtr)
405 Window w;
406 if ((w = X11DRV_WND_GetXWindow(wndPtr)))
408 XEvent xe;
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;
426 return TRUE;
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) )
460 CREATESTRUCTA cs;
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;
466 if (!cs.cy)
467 cs.cy = 1;
468 cs.cx = wndPtr->rectWindow.right - wndPtr->rectWindow.left;
469 if (!cs.cx)
470 cs.cx = 1;
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,
478 &cs, FALSE);
481 else /* a child window */
483 if( !( wndPtr->dwStyle & WS_CHILD ) )
485 if( wndPtr->wIDmenu != 0)
487 DestroyMenu( (HMENU) wndPtr->wIDmenu );
488 wndPtr->wIDmenu = 0;
492 WIN_LinkWindow(wndPtr->hwndSelf, HWND_TOP);
494 WIN_ReleaseDesktop();
495 return pWndPrev;
496 } /* failure */
497 WIN_ReleaseDesktop();
498 return 0;
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();
515 return;
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;
523 while (wndPtr)
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;
531 wndPtr = wndPrev;
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);
546 else
548 Window window, root, parent, *children;
549 int nchildren;
550 window = X11DRV_WND_GetXWindow(wndPtr);
551 for (;;)
553 TSXQueryTree( display, window, &root, &parent,
554 &children, &nchildren );
555 TSXFree( children );
556 if (parent == root)
557 return window;
558 window = parent;
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;
571 int changeMask = 0;
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) );
583 if(bChangePos)
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();
598 if (size_hints)
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 );
608 TSXFree(size_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 );
627 Window stack[2];
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 /*****************************************************************
657 * X11DRV_WND_SetText
659 void X11DRV_WND_SetText(WND *wndPtr, LPCSTR text)
661 if (!X11DRV_WND_GetXWindow(wndPtr))
662 return;
664 TSXStoreName( display, X11DRV_WND_GetXWindow(wndPtr), text );
665 TSXSetIconName( display, X11DRV_WND_GetXWindow(wndPtr), text );
668 /*****************************************************************
669 * X11DRV_WND_SetFocus
671 * Set the X focus.
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;
678 Window win;
679 WND *w = wndPtr;
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)
685 w = w->parent;
686 if (!w) w = wndPtr;
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 );
693 return;
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 );
707 EVENT_Synchronize();
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;
738 POINT dst, src;
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,
750 dst.x, dst.y );
751 if (bUpdate)
752 TSXSetGraphicsExposures( display, physDev->gc, False );
754 if (bUpdate) /* Make sure exposure events have been processed */
755 EVENT_Synchronize();
758 /***********************************************************************
759 * X11DRV_WND_SetDrawable
761 * Set the drawable, origin and dimensions for the DC associated to
762 * a given window.
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 */
772 dc->w.DCOrgX = 0;
773 dc->w.DCOrgY = 0;
774 physDev->drawable = X11DRV_GetXRootWindow();
775 TSXSetSubwindowMode( display, physDev->gc, IncludeInferiors );
777 else
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;
802 else
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 */
817 if ( offsetClipRgn )
819 OffsetRgn(dc->w.hClipRgn, dc->w.DCOrgX - dcOrgXCopy,dc->w.DCOrgY - dcOrgYCopy);
822 physDev->drawable = X11DRV_WND_GetXWindow(wndPtr);
824 #if 0
825 /* This is needed when we reuse a cached DC because
826 * SetDCState() called by ReleaseDC() screws up DC
827 * origins for child windows.
830 if( bSetClipOrigin )
831 TSXSetClipOrigin( display, physDev->gc, dc->w.DCOrgX, dc->w.DCOrgY );
832 #endif
836 /***********************************************************************
837 * X11DRV_SetWMHint
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();
843 if (wm_hints)
845 wm_hints->flags = hint;
846 switch( hint )
848 case InputHint:
849 wm_hints->input = val;
850 break;
852 case StateHint:
853 wm_hints->initial_state = val;
854 break;
856 case IconPixmapHint:
857 wm_hints->icon_pixmap = (Pixmap)val;
858 break;
860 case IconWindowHint:
861 wm_hints->icon_window = (Window)val;
862 break;
865 TSXSetWMHints( display, X11DRV_WND_GetXWindow(wndPtr), wm_hints );
866 TSXFree(wm_hints);
867 return TRUE;
869 return FALSE;
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)
882 Window w;
884 if( (w = X11DRV_WND_GetXWindow(wnd)) )
886 XSetWindowAttributes win_attr;
888 switch( ha )
890 case HAK_ICONICSTATE: /* called when a window is minimized/restored */
892 if( (wnd->flags & WIN_MANAGED) )
894 if( value )
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;
905 ev.format = 32;
906 ev.data.l[0] = IconicState;
907 ev.window = w;
909 if( TSXSendEvent (display,
910 RootWindow( display, XScreenNumberOfScreen(X11DRV_GetXScreen()) ),
911 True, (SubstructureRedirectMask | SubstructureNotifyMask), (XEvent*)&ev))
913 XEvent xe;
914 TSXFlush (display);
915 while( !TSXCheckTypedWindowEvent( display, w, UnmapNotify, &xe) );
917 else
918 break;
920 else
921 X11DRV_SetWMHint( display, wnd, StateHint, IconicState );
923 else
925 if( !(wnd->flags & WS_VISIBLE) )
926 X11DRV_SetWMHint( display, wnd, StateHint, NormalState );
927 else
929 XEvent xe;
930 TSXMapWindow(display, w );
931 while( !TSXCheckTypedWindowEvent( display, w, MapNotify, &xe) );
934 return TRUE;
936 break;
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 );
946 return TRUE;
948 case HAK_ICONS: /* called when the icons change */
949 if ( (wnd->flags & WIN_MANAGED) )
950 X11DRV_WND_UpdateIconHints(wnd);
951 return TRUE;
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 );
959 return FALSE;
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
977 * mapped.
979 * all others: to be added ;)
981 void X11DRV_WND_DockWindow(WND *wndPtr)
983 int data = 1;
984 Window win = X11DRV_WND_GetXWindow(wndPtr);
985 if (kwmDockWindow == None)
986 return; /* no KDE running */
987 TSXChangeProperty(
988 display,win,kwmDockWindow,kwmDockWindow,32,PropModeReplace,(char*)&data,1