4 * Copyright 1993, 1994, 1995, 1996 Alexandre Julliard
6 * 1995, 1996 Alex Korobka
11 #include <X11/Xatom.h>
22 #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_Initialize
102 void X11DRV_WND_Initialize(WND *wndPtr)
104 X11DRV_WND_DATA *pWndDriverData =
105 (X11DRV_WND_DATA *) HeapAlloc(SystemHeap, 0, sizeof(X11DRV_WND_DATA));
107 wndPtr->pDriverData = (void *) pWndDriverData;
109 pWndDriverData->window = 0;
112 /**********************************************************************
113 * X11DRV_WND_Finalize
115 void X11DRV_WND_Finalize(WND *wndPtr)
117 X11DRV_WND_DATA *pWndDriverData =
118 (X11DRV_WND_DATA *) wndPtr->pDriverData;
120 if (!wndPtr->pDriverData) {
121 ERR("Trying to destroy window again. Not good.\n");
124 if(pWndDriverData->window)
127 "WND destroyed without destroying "
128 "the associated X Window (%ld)\n",
129 pWndDriverData->window
132 HeapFree(SystemHeap, 0, wndPtr->pDriverData);
133 wndPtr->pDriverData = NULL;
136 /**********************************************************************
137 * X11DRV_WND_CreateDesktopWindow
139 BOOL X11DRV_WND_CreateDesktopWindow(WND *wndPtr, CLASS *classPtr, BOOL bUnicode)
141 if (wmProtocols == None)
142 wmProtocols = TSXInternAtom( display, "WM_PROTOCOLS", True );
143 if (wmDeleteWindow == None)
144 wmDeleteWindow = TSXInternAtom( display, "WM_DELETE_WINDOW", True );
145 if( dndProtocol == None )
146 dndProtocol = TSXInternAtom( display, "DndProtocol" , False );
147 if( dndSelection == None )
148 dndSelection = TSXInternAtom( display, "DndSelection" , False );
149 if( wmChangeState == None )
150 wmChangeState = TSXInternAtom (display, "WM_CHANGE_STATE", False);
151 if (kwmDockWindow == None)
152 kwmDockWindow = TSXInternAtom( display, "KWM_DOCKWINDOW", False );
154 ((X11DRV_WND_DATA *) wndPtr->pDriverData)->window = X11DRV_GetXRootWindow();
155 X11DRV_WND_RegisterWindow( wndPtr );
160 /**********************************************************************
161 * X11DRV_WND_IconChanged
163 * hIcon or hIconSm has changed (or is being initialised for the
164 * first time). Complete the X11 driver-specific initialisation.
166 * This is not entirely correct, may need to create
167 * an icon window and set the pixmap as a background
169 static void X11DRV_WND_IconChanged(WND *wndPtr)
172 HICON16 hIcon = NC_IconForWindow(wndPtr);
174 if( ((X11DRV_WND_DATA *) wndPtr->pDriverData)->hWMIconBitmap )
175 DeleteObject( ((X11DRV_WND_DATA *) wndPtr->pDriverData)->hWMIconBitmap );
177 if( ((X11DRV_WND_DATA *) wndPtr->pDriverData)->hWMIconMask )
178 DeleteObject( ((X11DRV_WND_DATA *) wndPtr->pDriverData)->hWMIconMask);
182 ((X11DRV_WND_DATA *) wndPtr->pDriverData)->hWMIconBitmap= 0;
183 ((X11DRV_WND_DATA *) wndPtr->pDriverData)->hWMIconMask= 0;
193 GetIconInfo(hIcon, &ii);
195 X11DRV_CreateBitmap(ii.hbmMask);
196 X11DRV_CreateBitmap(ii.hbmColor);
198 GetObjectA(ii.hbmMask, sizeof(bmMask), &bmMask);
201 rcMask.right = bmMask.bmWidth;
202 rcMask.bottom = bmMask.bmHeight;
204 hDC = CreateCompatibleDC(0);
205 hbmOrig = SelectObject(hDC, ii.hbmMask);
206 InvertRect(hDC, &rcMask);
207 SelectObject(hDC, hbmOrig);
210 ((X11DRV_WND_DATA *) wndPtr->pDriverData)->hWMIconBitmap = ii.hbmColor;
211 ((X11DRV_WND_DATA *) wndPtr->pDriverData)->hWMIconMask= ii.hbmMask;
216 static void X11DRV_WND_SetIconHints(WND *wndPtr, XWMHints *hints)
218 if (((X11DRV_WND_DATA *) wndPtr->pDriverData)->hWMIconBitmap)
221 = X11DRV_BITMAP_Pixmap(((X11DRV_WND_DATA *) wndPtr->pDriverData)->hWMIconBitmap);
222 hints->flags |= IconPixmapHint;
225 hints->flags &= ~IconPixmapHint;
227 if (((X11DRV_WND_DATA *) wndPtr->pDriverData)->hWMIconMask)
230 = X11DRV_BITMAP_Pixmap(((X11DRV_WND_DATA *) wndPtr->pDriverData)->hWMIconMask);
231 hints->flags |= IconMaskHint;
234 hints->flags &= ~IconMaskHint;
237 /**********************************************************************
238 * X11DRV_WND_UpdateIconHints
240 * hIcon or hIconSm has changed (or is being initialised for the
241 * first time). Complete the X11 driver-specific initialisation
242 * and set the window hints.
244 * This is not entirely correct, may need to create
245 * an icon window and set the pixmap as a background
247 static void X11DRV_WND_UpdateIconHints(WND *wndPtr)
251 X11DRV_WND_IconChanged(wndPtr);
253 wm_hints = TSXGetWMHints( display, X11DRV_WND_GetXWindow(wndPtr) );
254 if (!wm_hints) wm_hints = TSXAllocWMHints();
257 X11DRV_WND_SetIconHints(wndPtr, wm_hints);
258 TSXSetWMHints( display, X11DRV_WND_GetXWindow(wndPtr), wm_hints );
264 /**********************************************************************
265 * X11DRV_WND_CreateWindow
267 BOOL X11DRV_WND_CreateWindow(WND *wndPtr, CLASS *classPtr, CREATESTRUCTA *cs, BOOL bUnicode)
269 /* Create the X window (only for top-level windows, and then only */
270 /* when there's no desktop window) */
272 if ((X11DRV_GetXRootWindow() == DefaultRootWindow(display))
273 && (wndPtr->parent->hwndSelf == GetDesktopWindow()))
277 XSetWindowAttributes win_attr;
279 /* Create "managed" windows only if a title bar or resizable */
280 /* frame is required. */
281 if (WIN_WindowNeedsWMBorder(cs->style, cs->dwExStyle)) {
282 win_attr.event_mask = ExposureMask | KeyPressMask |
283 KeyReleaseMask | PointerMotionMask |
284 ButtonPressMask | ButtonReleaseMask |
285 FocusChangeMask | StructureNotifyMask;
286 win_attr.override_redirect = FALSE;
287 wndPtr->flags |= WIN_MANAGED;
289 win_attr.event_mask = ExposureMask | KeyPressMask |
290 KeyReleaseMask | PointerMotionMask |
291 ButtonPressMask | ButtonReleaseMask |
293 win_attr.override_redirect = TRUE;
295 wndPtr->flags |= WIN_NATIVE;
297 win_attr.bit_gravity = (classPtr->style & (CS_VREDRAW | CS_HREDRAW)) ? BGForget : BGNorthWest;
298 win_attr.colormap = X11DRV_PALETTE_PaletteXColormap;
299 win_attr.backing_store = NotUseful;
300 win_attr.save_under = ((classPtr->style & CS_SAVEBITS) != 0);
301 win_attr.cursor = X11DRV_MOUSE_XCursor;
303 ((X11DRV_WND_DATA *) wndPtr->pDriverData)->hWMIconBitmap = 0;
304 ((X11DRV_WND_DATA *) wndPtr->pDriverData)->hWMIconMask = 0;
305 ((X11DRV_WND_DATA *) wndPtr->pDriverData)->bit_gravity = win_attr.bit_gravity;
307 /* Zero-size X11 window hack. X doesn't like them, and will crash */
308 /* with a BadValue unless we do something ugly like this. */
309 /* FIXME: there must be a better way. */
310 if (cs->cx <= 0) cs->cx = 1;
311 if (cs->cy <= 0) cs->cy = 1;
314 ((X11DRV_WND_DATA *) wndPtr->pDriverData)->window =
315 TSXCreateWindow( display, X11DRV_GetXRootWindow(),
316 cs->x, cs->y, cs->cx, cs->cy,
318 InputOutput, CopyFromParent,
319 CWEventMask | CWOverrideRedirect |
320 CWColormap | CWCursor | CWSaveUnder |
321 CWBackingStore | CWBitGravity,
324 if(!(wGroupLeader = X11DRV_WND_GetXWindow(wndPtr)))
327 /* If we are the systray, we need to be managed to be noticed by KWM */
329 if (wndPtr->dwExStyle & WS_EX_TRAYWINDOW)
330 X11DRV_WND_DockWindow(wndPtr);
332 if (wndPtr->flags & WIN_MANAGED)
334 XClassHint *class_hints = TSXAllocClassHint();
335 XSizeHints* size_hints = TSXAllocSizeHints();
339 class_hints->res_name = "wineManaged";
340 class_hints->res_class = "Wine";
341 TSXSetClassHint( display, ((X11DRV_WND_DATA *) wndPtr->pDriverData)->window, class_hints );
342 TSXFree (class_hints);
347 size_hints->win_gravity = StaticGravity;
348 size_hints->flags = PWinGravity;
350 if (HAS_DLGFRAME(cs->style,cs->dwExStyle))
352 size_hints->min_width = size_hints->max_width = cs->cx;
353 size_hints->min_height = size_hints->max_height = cs->cy;
354 size_hints->flags |= PMinSize | PMaxSize;
357 TSXSetWMSizeHints( display, X11DRV_WND_GetXWindow(wndPtr),
358 size_hints, XA_WM_NORMAL_HINTS );
363 if (cs->hwndParent) /* Get window owner */
366 WND *tmpWnd = WIN_FindWndPtr(cs->hwndParent);
368 w = X11DRV_WND_FindXWindow( tmpWnd );
371 TSXSetTransientForHint( display, X11DRV_WND_GetXWindow(wndPtr), w );
374 WIN_ReleaseWndPtr(tmpWnd);
377 if ((wm_hints = TSXAllocWMHints()))
379 wm_hints->flags = InputHint | StateHint | WindowGroupHint;
380 wm_hints->input = True;
382 if( wndPtr->flags & WIN_MANAGED )
384 X11DRV_WND_IconChanged(wndPtr);
385 X11DRV_WND_SetIconHints(wndPtr, wm_hints);
387 wm_hints->initial_state = (wndPtr->dwStyle & WS_MINIMIZE)
388 ? IconicState : NormalState;
391 wm_hints->initial_state = NormalState;
392 wm_hints->window_group = wGroupLeader;
394 TSXSetWMHints( display, X11DRV_WND_GetXWindow(wndPtr), wm_hints );
397 X11DRV_WND_RegisterWindow( wndPtr );
402 /***********************************************************************
403 * X11DRV_WND_DestroyWindow
405 BOOL X11DRV_WND_DestroyWindow(WND *wndPtr)
408 if ((w = X11DRV_WND_GetXWindow(wndPtr)))
411 TSXDeleteContext( display, w, winContext );
412 TSXDestroyWindow( display, w );
413 while( TSXCheckWindowEvent(display, w, NoEventMask, &xe) );
415 ((X11DRV_WND_DATA *) wndPtr->pDriverData)->window = None;
416 if( ((X11DRV_WND_DATA *) wndPtr->pDriverData)->hWMIconBitmap )
418 DeleteObject( ((X11DRV_WND_DATA *) wndPtr->pDriverData)->hWMIconBitmap );
419 ((X11DRV_WND_DATA *) wndPtr->pDriverData)->hWMIconBitmap = 0;
421 if( ((X11DRV_WND_DATA *) wndPtr->pDriverData)->hWMIconMask )
423 DeleteObject( ((X11DRV_WND_DATA *) wndPtr->pDriverData)->hWMIconMask);
424 ((X11DRV_WND_DATA *) wndPtr->pDriverData)->hWMIconMask= 0;
431 /*****************************************************************
432 * X11DRV_WND_SetParent
434 WND *X11DRV_WND_SetParent(WND *wndPtr, WND *pWndParent)
436 WND *pDesktop = WIN_GetDesktop();
438 if( wndPtr && pWndParent && (wndPtr != pDesktop) )
440 WND* pWndPrev = wndPtr->parent;
442 if( pWndParent != pWndPrev )
444 if ( X11DRV_WND_GetXWindow(wndPtr) )
446 /* Toplevel window needs to be reparented. Used by Tk 8.0 */
448 TSXDestroyWindow( display, X11DRV_WND_GetXWindow(wndPtr) );
449 ((X11DRV_WND_DATA *) wndPtr->pDriverData)->window = None;
452 WIN_UnlinkWindow(wndPtr->hwndSelf);
453 wndPtr->parent = pWndParent;
455 /* Create an X counterpart for reparented top-level windows
456 * when not in the desktop mode. */
458 if( pWndParent == pDesktop )
460 if( X11DRV_GetXRootWindow() == DefaultRootWindow(display) )
463 cs.lpCreateParams = NULL;
464 cs.hInstance = 0; /* not used in following call */
465 cs.hMenu = 0; /* not used in following call */
466 cs.hwndParent = pWndParent->hwndSelf;
467 cs.cy = wndPtr->rectWindow.bottom - wndPtr->rectWindow.top;
470 cs.cx = wndPtr->rectWindow.right - wndPtr->rectWindow.left;
473 cs.y = wndPtr->rectWindow.top;
474 cs.x = wndPtr->rectWindow.left;
475 cs.style = wndPtr->dwStyle;
476 cs.lpszName = 0; /* not used in following call */
477 cs.lpszClass = 0; /*not used in following call */
478 cs.dwExStyle = wndPtr->dwExStyle;
479 X11DRV_WND_CreateWindow(wndPtr, wndPtr->class,
483 else /* a child window */
485 if( !( wndPtr->dwStyle & WS_CHILD ) )
487 if( wndPtr->wIDmenu != 0)
489 DestroyMenu( (HMENU) wndPtr->wIDmenu );
494 WIN_LinkWindow(wndPtr->hwndSelf, HWND_TOP);
496 WIN_ReleaseDesktop();
499 WIN_ReleaseDesktop();
503 /***********************************************************************
504 * X11DRV_WND_ForceWindowRaise
506 * Raise a window on top of the X stacking order, while preserving
507 * the correct Windows Z order.
509 void X11DRV_WND_ForceWindowRaise(WND *wndPtr)
511 XWindowChanges winChanges;
512 WND *wndPrev,*pDesktop = WIN_GetDesktop();
514 if( !wndPtr || !X11DRV_WND_GetXWindow(wndPtr) || (wndPtr->flags & WIN_MANAGED) )
516 WIN_ReleaseDesktop();
520 /* Raise all windows up to wndPtr according to their Z order.
521 * (it would be easier with sibling-related Below but it doesn't
522 * work very well with SGI mwm for instance)
524 winChanges.stack_mode = Above;
527 if (X11DRV_WND_GetXWindow(wndPtr))
528 TSXReconfigureWMWindow( display, X11DRV_WND_GetXWindow(wndPtr), 0,
529 CWStackMode, &winChanges );
530 wndPrev = pDesktop->child;
531 if (wndPrev == wndPtr) break;
532 while (wndPrev && (wndPrev->next != wndPtr)) wndPrev = wndPrev->next;
535 WIN_ReleaseDesktop();
538 /***********************************************************************
539 * X11DRV_WND_FindDesktopXWindow [Internal]
541 * Find the actual X window which needs be restacked.
542 * Used by X11DRV_WND_SetWindowPos().
544 static Window X11DRV_WND_FindDesktopXWindow( WND *wndPtr )
546 if (!(wndPtr->flags & WIN_MANAGED))
547 return X11DRV_WND_GetXWindow(wndPtr);
550 Window window, root, parent, *children;
552 window = X11DRV_WND_GetXWindow(wndPtr);
555 TSXQueryTree( display, window, &root, &parent,
556 &children, &nchildren );
565 /***********************************************************************
566 * WINPOS_SetXWindowPos
568 * SetWindowPos() for an X window. Used by the real SetWindowPos().
570 void X11DRV_WND_SetWindowPos(WND *wndPtr, const WINDOWPOS *winpos, BOOL bChangePos)
572 XWindowChanges winChanges;
574 WND *winposPtr = WIN_FindWndPtr( winpos->hwnd );
575 if ( !winposPtr ) return;
577 if(!wndPtr->hwndSelf) wndPtr = NULL; /* FIXME: WND destroyed, shouldn't happen!!! */
579 if (!(winpos->flags & SWP_SHOWWINDOW) && (winpos->flags & SWP_HIDEWINDOW))
581 if(X11DRV_WND_GetXWindow(wndPtr))
582 TSXUnmapWindow( display, X11DRV_WND_GetXWindow(wndPtr) );
587 if ( !(winpos->flags & SWP_NOSIZE))
589 winChanges.width = (winpos->cx > 0 ) ? winpos->cx : 1;
590 winChanges.height = (winpos->cy > 0 ) ? winpos->cy : 1;
591 changeMask |= CWWidth | CWHeight;
593 /* Tweak dialog window size hints */
595 if ((winposPtr->flags & WIN_MANAGED) &&
596 HAS_DLGFRAME(winposPtr->dwStyle,winposPtr->dwExStyle))
598 XSizeHints *size_hints = TSXAllocSizeHints();
602 long supplied_return;
604 TSXGetWMSizeHints( display, X11DRV_WND_GetXWindow(winposPtr), size_hints,
605 &supplied_return, XA_WM_NORMAL_HINTS);
606 size_hints->min_width = size_hints->max_width = winpos->cx;
607 size_hints->min_height = size_hints->max_height = winpos->cy;
608 TSXSetWMSizeHints( display, X11DRV_WND_GetXWindow(winposPtr), size_hints,
609 XA_WM_NORMAL_HINTS );
614 if (!(winpos->flags & SWP_NOMOVE))
616 winChanges.x = winpos->x;
617 winChanges.y = winpos->y;
618 changeMask |= CWX | CWY;
620 if (!(winpos->flags & SWP_NOZORDER))
622 winChanges.stack_mode = Below;
623 changeMask |= CWStackMode;
625 if (winpos->hwndInsertAfter == HWND_TOP) winChanges.stack_mode = Above;
626 else if (winpos->hwndInsertAfter != HWND_BOTTOM)
628 WND* insertPtr = WIN_FindWndPtr( winpos->hwndInsertAfter );
631 stack[0] = X11DRV_WND_FindDesktopXWindow( insertPtr );
632 stack[1] = X11DRV_WND_FindDesktopXWindow( winposPtr );
634 /* for stupid window managers (i.e. all of them) */
636 TSXRestackWindows(display, stack, 2);
637 changeMask &= ~CWStackMode;
639 WIN_ReleaseWndPtr(insertPtr);
642 if (changeMask && X11DRV_WND_GetXWindow(winposPtr))
644 TSXReconfigureWMWindow( display, X11DRV_WND_GetXWindow(winposPtr), 0, changeMask, &winChanges );
645 if( winposPtr->class->style & (CS_VREDRAW | CS_HREDRAW) )
646 X11DRV_WND_SetHostAttr( winposPtr, HAK_BITGRAVITY, BGForget );
650 if ( winpos->flags & SWP_SHOWWINDOW )
652 if(X11DRV_WND_GetXWindow(wndPtr))
653 TSXMapWindow( display, X11DRV_WND_GetXWindow(wndPtr) );
655 WIN_ReleaseWndPtr(winposPtr);
658 /*****************************************************************
661 void X11DRV_WND_SetText(WND *wndPtr, LPCWSTR text)
665 static UINT text_cp = (UINT)-1;
668 if (!(win = X11DRV_WND_GetXWindow(wndPtr))) return;
670 if(text_cp == (UINT)-1)
672 text_cp = PROFILE_GetWineIniInt("x11drv", "TextCP", CP_ACP);
673 TRACE("text_cp = %u\n", text_cp);
676 /* allocate new buffer for window text */
677 count = WideCharToMultiByte(text_cp, 0, text, -1, NULL, 0, NULL, NULL);
678 if (!(buffer = HeapAlloc( GetProcessHeap(), 0, count * sizeof(WCHAR) )))
680 ERR("Not enough memory for window text\n");
683 WideCharToMultiByte(text_cp, 0, text, -1, buffer, count, NULL, NULL);
685 TSXStoreName( display, win, buffer );
686 TSXSetIconName( display, win, buffer );
687 HeapFree( GetProcessHeap(), 0, buffer );
690 /*****************************************************************
691 * X11DRV_WND_SetFocus
694 * Explicit colormap management seems to work only with OLVWM.
696 void X11DRV_WND_SetFocus(WND *wndPtr)
698 HWND hwnd = wndPtr->hwndSelf;
699 XWindowAttributes win_attr;
703 /* Only mess with the X focus if there's */
704 /* no desktop window and if the window is not managed by the WM. */
705 if ((X11DRV_GetXRootWindow() != DefaultRootWindow(display))) return;
706 while (w && !((X11DRV_WND_DATA *) w->pDriverData)->window)
709 if (w->flags & WIN_MANAGED) return;
711 if (!hwnd) /* If setting the focus to 0, uninstall the colormap */
713 if (X11DRV_PALETTE_PaletteFlags & X11DRV_PALETTE_PRIVATE)
714 TSXUninstallColormap( display, X11DRV_PALETTE_PaletteXColormap );
718 /* Set X focus and install colormap */
720 if (!(win = X11DRV_WND_FindXWindow(wndPtr))) return;
721 if (!TSXGetWindowAttributes( display, win, &win_attr ) ||
722 (win_attr.map_state != IsViewable))
723 return; /* If window is not viewable, don't change anything */
725 TSXSetInputFocus( display, win, RevertToParent, CurrentTime );
726 if (X11DRV_PALETTE_PaletteFlags & X11DRV_PALETTE_PRIVATE)
727 TSXInstallColormap( display, X11DRV_PALETTE_PaletteXColormap );
732 /*****************************************************************
733 * X11DRV_WND_PreSizeMove
735 void X11DRV_WND_PreSizeMove(WND *wndPtr)
737 if (!(wndPtr->dwStyle & WS_CHILD) && (X11DRV_GetXRootWindow() == DefaultRootWindow(display)))
738 TSXGrabServer( display );
741 /*****************************************************************
742 * X11DRV_WND_PostSizeMove
744 void X11DRV_WND_PostSizeMove(WND *wndPtr)
746 if (!(wndPtr->dwStyle & WS_CHILD) &&
747 (X11DRV_GetXRootWindow() == DefaultRootWindow(display)))
748 TSXUngrabServer( display );
751 /*****************************************************************
752 * X11DRV_WND_SurfaceCopy
754 * Copies rect to (rect.left + dx, rect.top + dy).
756 void X11DRV_WND_SurfaceCopy(WND* wndPtr, DC *dcPtr, INT dx, INT dy,
757 const RECT *rect, BOOL bUpdate)
759 X11DRV_PDEVICE *physDev = (X11DRV_PDEVICE *)dcPtr->physDev;
762 dst.x = (src.x = dcPtr->w.DCOrgX + rect->left) + dx;
763 dst.y = (src.y = dcPtr->w.DCOrgY + rect->top) + dy;
765 if (bUpdate) /* handles non-Wine windows hanging over the copied area */
766 TSXSetGraphicsExposures( display, physDev->gc, True );
767 TSXSetFunction( display, physDev->gc, GXcopy );
768 TSXCopyArea( display, physDev->drawable, physDev->drawable,
769 physDev->gc, src.x, src.y,
770 rect->right - rect->left,
771 rect->bottom - rect->top,
774 TSXSetGraphicsExposures( display, physDev->gc, False );
776 if (bUpdate) /* Make sure exposure events have been processed */
780 /***********************************************************************
781 * X11DRV_WND_SetDrawable
783 * Set the drawable, origin and dimensions for the DC associated to
786 void X11DRV_WND_SetDrawable(WND *wndPtr, DC *dc, WORD flags, BOOL bSetClipOrigin)
788 X11DRV_PDEVICE *physDev = (X11DRV_PDEVICE *)dc->physDev;
789 INT dcOrgXCopy = 0, dcOrgYCopy = 0;
790 BOOL offsetClipRgn = FALSE;
792 if (!wndPtr) /* Get a DC for the whole screen */
796 physDev->drawable = X11DRV_GetXRootWindow();
797 TSXSetSubwindowMode( display, physDev->gc, IncludeInferiors );
802 * This function change the coordinate system (DCOrgX,DCOrgY)
803 * values. When it moves the origin, other data like the current clipping
804 * region will not be moved to that new origin. In the case of DCs that are class
805 * or window DCs that clipping region might be a valid value from a previous use
806 * of the DC and changing the origin of the DC without moving the clip region
807 * results in a clip region that is not placed properly in the DC.
808 * This code will save the dc origin, let the SetDrawable
809 * modify the origin and reset the clipping. When the clipping is set,
810 * it is moved according to the new DC origin.
812 if ( (wndPtr->class->style & (CS_OWNDC | CS_CLASSDC)) && (dc->w.hClipRgn > 0))
814 dcOrgXCopy = dc->w.DCOrgX;
815 dcOrgYCopy = dc->w.DCOrgY;
816 offsetClipRgn = TRUE;
819 if (flags & DCX_WINDOW)
821 dc->w.DCOrgX = wndPtr->rectWindow.left;
822 dc->w.DCOrgY = wndPtr->rectWindow.top;
826 dc->w.DCOrgX = wndPtr->rectClient.left;
827 dc->w.DCOrgY = wndPtr->rectClient.top;
829 while (!X11DRV_WND_GetXWindow(wndPtr))
831 wndPtr = wndPtr->parent;
832 dc->w.DCOrgX += wndPtr->rectClient.left;
833 dc->w.DCOrgY += wndPtr->rectClient.top;
835 dc->w.DCOrgX -= wndPtr->rectWindow.left;
836 dc->w.DCOrgY -= wndPtr->rectWindow.top;
838 /* reset the clip region, according to the new origin */
841 OffsetRgn(dc->w.hClipRgn, dc->w.DCOrgX - dcOrgXCopy,dc->w.DCOrgY - dcOrgYCopy);
844 physDev->drawable = X11DRV_WND_GetXWindow(wndPtr);
847 /* This is needed when we reuse a cached DC because
848 * SetDCState() called by ReleaseDC() screws up DC
849 * origins for child windows.
853 TSXSetClipOrigin( display, physDev->gc, dc->w.DCOrgX, dc->w.DCOrgY );
858 /***********************************************************************
861 static BOOL X11DRV_SetWMHint(Display* display, WND* wndPtr, int hint, int val)
863 XWMHints* wm_hints = TSXGetWMHints( display, X11DRV_WND_GetXWindow(wndPtr) );
864 if (!wm_hints) wm_hints = TSXAllocWMHints();
867 wm_hints->flags = hint;
871 wm_hints->input = val;
875 wm_hints->initial_state = val;
879 wm_hints->icon_pixmap = (Pixmap)val;
883 wm_hints->icon_window = (Window)val;
887 TSXSetWMHints( display, X11DRV_WND_GetXWindow(wndPtr), wm_hints );
895 /***********************************************************************
896 * X11DRV_WND_SetHostAttr
898 * This function returns TRUE if the attribute is supported and the
899 * action was successful. Otherwise it should return FALSE and Wine will try
900 * to get by without the functionality provided by the host window system.
902 BOOL X11DRV_WND_SetHostAttr(WND* wnd, INT ha, INT value)
906 if( (w = X11DRV_WND_GetXWindow(wnd)) )
908 XSetWindowAttributes win_attr;
912 case HAK_ICONICSTATE: /* called when a window is minimized/restored */
914 if( (wnd->flags & WIN_MANAGED) )
918 if( wnd->dwStyle & WS_VISIBLE )
920 XClientMessageEvent ev;
922 /* FIXME: set proper icon */
924 ev.type = ClientMessage;
925 ev.display = display;
926 ev.message_type = wmChangeState;
928 ev.data.l[0] = IconicState;
931 if( TSXSendEvent (display,
932 RootWindow( display, XScreenNumberOfScreen(X11DRV_GetXScreen()) ),
933 True, (SubstructureRedirectMask | SubstructureNotifyMask), (XEvent*)&ev))
937 while( !TSXCheckTypedWindowEvent( display, w, UnmapNotify, &xe) );
943 X11DRV_SetWMHint( display, wnd, StateHint, IconicState );
947 if( !(wnd->flags & WS_VISIBLE) )
948 X11DRV_SetWMHint( display, wnd, StateHint, NormalState );
952 TSXMapWindow(display, w );
953 while( !TSXCheckTypedWindowEvent( display, w, MapNotify, &xe) );
960 case HAK_BITGRAVITY: /* called when a window is resized */
962 if( ((X11DRV_WND_DATA *) wnd->pDriverData)->bit_gravity != value )
964 win_attr.bit_gravity = value;
965 ((X11DRV_WND_DATA *) wnd->pDriverData)->bit_gravity = value;
966 TSXChangeWindowAttributes( display, w, CWBitGravity, &win_attr );
970 case HAK_ICONS: /* called when the icons change */
971 if ( (wnd->flags & WIN_MANAGED) )
972 X11DRV_WND_UpdateIconHints(wnd);
975 case HAK_ACCEPTFOCUS: /* called when a window is disabled/enabled */
977 if( (wnd->flags & WIN_MANAGED) )
978 return X11DRV_SetWMHint( display, wnd, InputHint, value );
984 /***********************************************************************
985 * X11DRV_WND_IsSelfClipping
987 BOOL X11DRV_WND_IsSelfClipping(WND *wndPtr)
989 return X11DRV_WND_GetXWindow(wndPtr) != None;
992 /***********************************************************************
993 * X11DRV_WND_DockWindow
995 * Set the X Property of the window that tells the windowmanager we really
996 * want to be in the systray
998 * KDE: set "KWM_DOCKWINDOW", type "KWM_DOCKWINDOW" to 1 before a window is
1001 * all others: to be added ;)
1003 void X11DRV_WND_DockWindow(WND *wndPtr)
1006 Window win = X11DRV_WND_GetXWindow(wndPtr);
1007 if (kwmDockWindow == None)
1008 return; /* no KDE running */
1010 display,win,kwmDockWindow,kwmDockWindow,32,PropModeReplace,(char*)&data,1
1015 /***********************************************************************
1016 * X11DRV_WND_SetWindowRgn
1018 * Assign specified region to window (for non-rectangular windows)
1020 void X11DRV_WND_SetWindowRgn(WND *wndPtr, HRGN hrgnWnd)
1022 #ifdef HAVE_LIBXSHAPE
1023 Window win = X11DRV_WND_GetXWindow(wndPtr);
1029 TSXShapeCombineMask( display, win, ShapeBounding, 0, 0, None, ShapeSet );
1035 DWORD dwBufferSize = GetRegionData(hrgnWnd, 0, NULL);
1036 PRGNDATA pRegionData = HeapAlloc(GetProcessHeap(), 0, dwBufferSize);
1037 if (!pRegionData) return;
1039 GetRegionData(hrgnWnd, dwBufferSize, pRegionData);
1040 size = pRegionData->rdh.nCount;
1041 /* convert region's "Windows rectangles" to XRectangles */
1042 aXRect = HeapAlloc(GetProcessHeap(), 0, size * sizeof(*aXRect) );
1045 XRectangle* pCurrRect = aXRect;
1046 RECT *pRect = (RECT*) pRegionData->Buffer;
1047 for (; pRect < ((RECT*) pRegionData->Buffer) + size ; ++pRect, ++pCurrRect)
1049 pCurrRect->x = pRect->left;
1050 pCurrRect->y = pRect->top;
1051 pCurrRect->height = pRect->bottom - pRect->top;
1052 pCurrRect->width = pRect->right - pRect->left;
1054 TRACE("Rectangle %04d of %04ld data: X=%04d, Y=%04d, Height=%04d, Width=%04d.\n",
1055 pRect - (RECT*) pRegionData->Buffer,
1063 /* shape = non-rectangular windows (X11/extensions) */
1064 TSXShapeCombineRectangles( display, win, ShapeBounding,
1066 pCurrRect - aXRect, ShapeSet, YXBanded );
1067 HeapFree(GetProcessHeap(), 0, aXRect );
1069 HeapFree(GetProcessHeap(), 0, pRegionData);
1071 #endif /* HAVE_LIBXSHAPE */