2 * Window related functions
4 * Copyright 1993, 1994, 1995, 1996, 2001 Alexandre Julliard
5 * Copyright 1993 David Metcalfe
6 * Copyright 1995, 1996 Alex Korobka
21 #include "debugtools.h"
27 DEFAULT_DEBUG_CHANNEL(x11drv);
29 extern Pixmap X11DRV_BITMAP_Pixmap( HBITMAP );
31 #define HAS_DLGFRAME(style,exStyle) \
32 (((exStyle) & WS_EX_DLGMODALFRAME) || \
33 (((style) & WS_DLGFRAME) && !((style) & WS_THICKFRAME)))
35 #define HAS_THICKFRAME(style,exStyle) \
36 (((style) & WS_THICKFRAME) && \
37 !(((style) & (WS_DLGFRAME|WS_BORDER)) == WS_DLGFRAME))
39 #define HAS_THINFRAME(style) \
40 (((style) & WS_BORDER) || !((style) & (WS_CHILD | WS_POPUP)))
42 /* X context to associate a hwnd to an X window */
43 XContext winContext = 0;
45 Atom wmProtocols = None;
46 Atom wmDeleteWindow = None;
47 Atom wmTakeFocus = None;
48 Atom dndProtocol = None;
49 Atom dndSelection = None;
50 Atom wmChangeState = None;
51 Atom kwmDockWindow = None;
52 Atom _kde_net_wm_system_tray_window_for = None; /* KDE 2 Final */
55 /***********************************************************************
58 * Check if a given window should be managed
60 inline static BOOL is_window_managed( WND *win )
62 if (!Options.managed) return FALSE;
64 /* tray window is always managed */
65 if (win->dwExStyle & WS_EX_TRAYWINDOW) return TRUE;
66 /* child windows are not managed */
67 if (win->dwStyle & WS_CHILD) return FALSE;
68 /* tool windows are not managed */
69 if (win->dwExStyle & WS_EX_TOOLWINDOW) return FALSE;
70 /* windows with caption or thick frame are managed */
71 if ((win->dwStyle & WS_CAPTION) == WS_CAPTION) return TRUE;
72 if (win->dwStyle & WS_THICKFRAME) return TRUE;
73 /* default: not managed */
78 /***********************************************************************
81 * Check if a given window is a top level X11 window
83 inline static BOOL is_window_top_level( WND *win )
85 return (root_window == DefaultRootWindow(gdi_display) &&
86 win->parent->hwndSelf == GetDesktopWindow());
90 /***********************************************************************
91 * is_client_window_mapped
93 * Check if the X client window should be mapped
95 inline static BOOL is_client_window_mapped( WND *win )
97 struct x11drv_win_data *data = win->pDriverData;
98 return !IsIconic( win->hwndSelf ) && !IsRectEmpty( &data->client_rect );
102 /***********************************************************************
103 * get_window_attributes
105 * Fill the window attributes structure for an X window.
106 * Returned cursor must be freed by caller.
108 static int get_window_attributes( Display *display, WND *win, XSetWindowAttributes *attr )
110 BOOL is_top_level = is_window_top_level( win );
111 BOOL managed = is_top_level && is_window_managed( win );
113 if (managed) win->dwExStyle |= WS_EX_MANAGED;
114 else win->dwExStyle &= ~WS_EX_MANAGED;
116 attr->override_redirect = !managed;
117 attr->colormap = X11DRV_PALETTE_PaletteXColormap;
118 attr->save_under = ((win->clsStyle & CS_SAVEBITS) != 0);
120 attr->event_mask = (ExposureMask | KeyPressMask | KeyReleaseMask | PointerMotionMask |
121 ButtonPressMask | ButtonReleaseMask);
122 if (is_window_top_level( win ))
124 attr->event_mask |= StructureNotifyMask | FocusChangeMask;
125 attr->cursor = X11DRV_GetCursor( display, GlobalLock16(GetCursor()) );
127 return (CWOverrideRedirect | CWSaveUnder | CWEventMask | CWColormap | CWCursor);
131 /***********************************************************************
134 * Change the X window attributes when the window style has changed.
136 static void sync_window_style( Display *display, WND *win )
138 XSetWindowAttributes attr;
142 mask = get_window_attributes( display, win, &attr );
143 XChangeWindowAttributes( display, get_whole_window(win), mask, &attr );
144 if (attr.cursor) XFreeCursor( display, attr.cursor );
149 /***********************************************************************
152 * fill the window changes structure
154 static int get_window_changes( XWindowChanges *changes, const RECT *old, const RECT *new )
158 if (old->right - old->left != new->right - new->left )
160 if (!(changes->width = new->right - new->left)) changes->width = 1;
163 if (old->bottom - old->top != new->bottom - new->top)
165 if (!(changes->height = new->bottom - new->top)) changes->height = 1;
168 if (old->left != new->left)
170 changes->x = new->left;
173 if (old->top != new->top)
175 changes->y = new->top;
182 /***********************************************************************
185 static Window create_icon_window( Display *display, WND *win )
187 struct x11drv_win_data *data = win->pDriverData;
188 XSetWindowAttributes attr;
190 attr.event_mask = (ExposureMask | KeyPressMask | KeyReleaseMask | PointerMotionMask |
191 ButtonPressMask | ButtonReleaseMask);
192 attr.bit_gravity = NorthWestGravity;
193 attr.backing_store = NotUseful/*WhenMapped*/;
196 data->icon_window = XCreateWindow( display, root_window, 0, 0,
197 GetSystemMetrics( SM_CXICON ),
198 GetSystemMetrics( SM_CYICON ),
201 CWEventMask | CWBitGravity | CWBackingStore, &attr );
202 XSaveContext( display, data->icon_window, winContext, (char *)win->hwndSelf );
205 TRACE( "created %lx\n", data->icon_window );
206 SetPropA( win->hwndSelf, "__wine_x11_icon_window", (HANDLE)data->icon_window );
207 return data->icon_window;
212 /***********************************************************************
213 * destroy_icon_window
215 inline static void destroy_icon_window( Display *display, WND *win )
217 struct x11drv_win_data *data = win->pDriverData;
219 if (!data->icon_window) return;
220 XDeleteContext( display, data->icon_window, winContext );
221 XDestroyWindow( display, data->icon_window );
222 data->icon_window = 0;
223 RemovePropA( win->hwndSelf, "__wine_x11_icon_window" );
227 /***********************************************************************
230 * Set the icon wm hints
232 static void set_icon_hints( Display *display, WND *wndPtr, XWMHints *hints )
234 X11DRV_WND_DATA *data = wndPtr->pDriverData;
235 HICON hIcon = GetClassLongA( wndPtr->hwndSelf, GCL_HICON );
237 if (data->hWMIconBitmap) DeleteObject( data->hWMIconBitmap );
238 if (data->hWMIconMask) DeleteObject( data->hWMIconMask);
239 data->hWMIconBitmap = 0;
240 data->hWMIconMask = 0;
242 if (!(wndPtr->dwExStyle & WS_EX_MANAGED))
244 destroy_icon_window( display, wndPtr );
245 hints->flags &= ~(IconPixmapHint | IconMaskHint | IconWindowHint);
249 if (!data->icon_window) create_icon_window( display, wndPtr );
250 hints->icon_window = data->icon_window;
251 hints->flags = (hints->flags & ~(IconPixmapHint | IconMaskHint)) | IconWindowHint;
261 GetIconInfo(hIcon, &ii);
263 X11DRV_CreateBitmap(ii.hbmMask);
264 X11DRV_CreateBitmap(ii.hbmColor);
266 GetObjectA(ii.hbmMask, sizeof(bmMask), &bmMask);
269 rcMask.right = bmMask.bmWidth;
270 rcMask.bottom = bmMask.bmHeight;
272 hDC = CreateCompatibleDC(0);
273 hbmOrig = SelectObject(hDC, ii.hbmMask);
274 InvertRect(hDC, &rcMask);
275 SelectObject(hDC, hbmOrig);
278 data->hWMIconBitmap = ii.hbmColor;
279 data->hWMIconMask = ii.hbmMask;
281 hints->icon_pixmap = X11DRV_BITMAP_Pixmap(data->hWMIconBitmap);
282 hints->icon_mask = X11DRV_BITMAP_Pixmap(data->hWMIconMask);
283 destroy_icon_window( display, wndPtr );
284 hints->flags = (hints->flags & ~IconWindowHint) | IconPixmapHint | IconMaskHint;
289 /***********************************************************************
292 * set the window size hints
294 static void set_size_hints( Display *display, WND *win )
296 XSizeHints* size_hints;
297 struct x11drv_win_data *data = win->pDriverData;
299 if ((size_hints = XAllocSizeHints()))
301 size_hints->win_gravity = StaticGravity;
302 size_hints->x = data->whole_rect.left;
303 size_hints->y = data->whole_rect.top;
304 size_hints->flags = PWinGravity | PPosition;
306 if (HAS_DLGFRAME( win->dwStyle, win->dwExStyle ))
308 size_hints->max_width = data->whole_rect.right - data->whole_rect.left;
309 size_hints->max_height = data->whole_rect.bottom - data->whole_rect.top;
310 size_hints->min_width = size_hints->max_width;
311 size_hints->min_height = size_hints->max_height;
312 size_hints->flags |= PMinSize | PMaxSize;
314 XSetWMNormalHints( display, data->whole_window, size_hints );
320 /***********************************************************************
323 * Set the window manager hints for a newly-created window
325 static void set_wm_hints( Display *display, WND *win )
327 struct x11drv_win_data *data = win->pDriverData;
329 XClassHint *class_hints;
338 protocols[i++] = wmDeleteWindow;
339 if (wmTakeFocus) protocols[i++] = wmTakeFocus;
340 XSetWMProtocols( display, data->whole_window, protocols, i );
343 if ((class_hints = XAllocClassHint()))
345 class_hints->res_name = "wine";
346 class_hints->res_class = "Wine";
347 XSetClassHint( display, data->whole_window, class_hints );
348 XFree( class_hints );
351 /* transient for hint */
354 struct x11drv_win_data *owner_data = win->owner->pDriverData;
355 XSetTransientForHint( display, data->whole_window, owner_data->whole_window );
356 group_leader = owner_data->whole_window;
358 else group_leader = data->whole_window;
361 if ((wm_hints = XAllocWMHints()))
363 wm_hints->flags = InputHint | StateHint | WindowGroupHint;
364 /* use globally active model if take focus is supported,
365 * passive model otherwise (cf. ICCCM) */
366 wm_hints->input = !wmTakeFocus;
368 set_icon_hints( display, win, wm_hints );
370 wm_hints->initial_state = (win->dwStyle & WS_MINIMIZE) ? IconicState : NormalState;
371 wm_hints->window_group = group_leader;
373 XSetWMHints( display, data->whole_window, wm_hints );
378 set_size_hints( display, win );
380 /* systray properties (KDE only for now) */
381 if (win->dwExStyle & WS_EX_TRAYWINDOW)
384 if (kwmDockWindow != None)
385 TSXChangeProperty( display, data->whole_window, kwmDockWindow, kwmDockWindow,
386 32, PropModeReplace, (char*)&val, 1 );
387 if (_kde_net_wm_system_tray_window_for != None)
388 TSXChangeProperty( display, data->whole_window, _kde_net_wm_system_tray_window_for,
389 XA_WINDOW, 32, PropModeReplace, (char*)&data->whole_window, 1 );
396 /***********************************************************************
397 * X11DRV_set_iconic_state
399 * Set the X11 iconic state according to the window style.
401 void X11DRV_set_iconic_state( WND *win )
403 Display *display = thread_display();
404 struct x11drv_win_data *data = win->pDriverData;
406 BOOL iconic = IsIconic( win->hwndSelf );
408 if (!(win->dwExStyle & WS_EX_MANAGED))
410 if (iconic) TSXUnmapWindow( display, data->client_window );
411 else if (is_client_window_mapped( win )) TSXMapWindow( display, data->client_window );
416 if (!(wm_hints = XGetWMHints( display, data->whole_window ))) wm_hints = XAllocWMHints();
417 wm_hints->flags |= StateHint | IconPositionHint;
418 wm_hints->initial_state = iconic ? IconicState : NormalState;
419 wm_hints->icon_x = win->rectWindow.left;
420 wm_hints->icon_y = win->rectWindow.top;
421 XSetWMHints( display, data->whole_window, wm_hints );
423 if (win->dwStyle & WS_VISIBLE)
426 XIconifyWindow( display, data->whole_window, DefaultScreen(display) );
428 if (!IsRectEmpty( &win->rectWindow )) XMapWindow( display, data->whole_window );
436 /***********************************************************************
437 * X11DRV_window_to_X_rect
439 * Convert a rect from client to X window coordinates
441 void X11DRV_window_to_X_rect( WND *win, RECT *rect )
443 if (!(win->dwExStyle & WS_EX_MANAGED)) return;
444 if (win->dwStyle & WS_ICONIC) return;
445 if (IsRectEmpty( rect )) return;
447 if (HAS_THICKFRAME( win->dwStyle, win->dwExStyle ))
448 InflateRect( rect, -GetSystemMetrics(SM_CXFRAME), -GetSystemMetrics(SM_CYFRAME) );
449 else if (HAS_DLGFRAME( win->dwStyle, win->dwExStyle ))
450 InflateRect( rect, -GetSystemMetrics(SM_CXDLGFRAME), -GetSystemMetrics(SM_CYDLGFRAME) );
451 else if (HAS_THINFRAME( win->dwStyle ))
452 InflateRect( rect, -GetSystemMetrics(SM_CXBORDER), -GetSystemMetrics(SM_CYBORDER) );
454 if ((win->dwStyle & WS_CAPTION) == WS_CAPTION)
456 if (win->dwExStyle & WS_EX_TOOLWINDOW)
457 rect->top += GetSystemMetrics(SM_CYSMCAPTION);
459 rect->top += GetSystemMetrics(SM_CYCAPTION);
462 if (win->dwExStyle & WS_EX_CLIENTEDGE)
463 InflateRect( rect, -GetSystemMetrics(SM_CXEDGE), -GetSystemMetrics(SM_CYEDGE) );
464 if (win->dwExStyle & WS_EX_STATICEDGE)
465 InflateRect( rect, -GetSystemMetrics(SM_CXBORDER), -GetSystemMetrics(SM_CYBORDER) );
467 if (rect->top >= rect->bottom) rect->bottom = rect->top + 1;
468 if (rect->left >= rect->right) rect->right = rect->left + 1;
472 /***********************************************************************
473 * X11DRV_X_to_window_rect
475 * Opposite of X11DRV_window_to_X_rect
477 void X11DRV_X_to_window_rect( WND *win, RECT *rect )
479 if (!(win->dwExStyle & WS_EX_MANAGED)) return;
480 if (win->dwStyle & WS_ICONIC) return;
481 if (IsRectEmpty( rect )) return;
483 if (HAS_THICKFRAME( win->dwStyle, win->dwExStyle ))
484 InflateRect( rect, GetSystemMetrics(SM_CXFRAME), GetSystemMetrics(SM_CYFRAME) );
485 else if (HAS_DLGFRAME( win->dwStyle, win->dwExStyle ))
486 InflateRect( rect, GetSystemMetrics(SM_CXDLGFRAME), GetSystemMetrics(SM_CYDLGFRAME) );
487 else if (HAS_THINFRAME( win->dwStyle ))
488 InflateRect( rect, GetSystemMetrics(SM_CXBORDER), GetSystemMetrics(SM_CYBORDER) );
490 if ((win->dwStyle & WS_CAPTION) == WS_CAPTION)
492 if (win->dwExStyle & WS_EX_TOOLWINDOW)
493 rect->top -= GetSystemMetrics(SM_CYSMCAPTION);
495 rect->top -= GetSystemMetrics(SM_CYCAPTION);
498 if (win->dwExStyle & WS_EX_CLIENTEDGE)
499 InflateRect( rect, GetSystemMetrics(SM_CXEDGE), GetSystemMetrics(SM_CYEDGE) );
500 if (win->dwExStyle & WS_EX_STATICEDGE)
501 InflateRect( rect, GetSystemMetrics(SM_CXBORDER), GetSystemMetrics(SM_CYBORDER) );
503 if (rect->top >= rect->bottom) rect->bottom = rect->top + 1;
504 if (rect->left >= rect->right) rect->right = rect->left + 1;
508 /***********************************************************************
509 * X11DRV_sync_whole_window_position
511 * Synchronize the X whole window position with the Windows one
513 int X11DRV_sync_whole_window_position( Display *display, WND *win, int zorder )
515 XWindowChanges changes;
517 struct x11drv_win_data *data = win->pDriverData;
518 RECT whole_rect = win->rectWindow;
520 X11DRV_window_to_X_rect( win, &whole_rect );
521 mask = get_window_changes( &changes, &data->whole_rect, &whole_rect );
525 /* find window that this one must be after */
526 WND *prev = win->parent->child;
527 if (prev == win) /* top child */
529 changes.stack_mode = Above;
534 while (prev && prev->next != win) prev = prev->next;
537 changes.stack_mode = Below;
538 changes.sibling = get_whole_window(prev);
539 mask |= CWStackMode | CWSibling;
541 else ERR( "previous window not found for %x, list corrupted?\n", win->hwndSelf );
545 data->whole_rect = whole_rect;
549 TRACE( "setting win %lx pos %d,%d,%dx%d after %lx changes=%x\n",
550 data->whole_window, whole_rect.left, whole_rect.top,
551 whole_rect.right - whole_rect.left, whole_rect.bottom - whole_rect.top,
552 changes.sibling, mask );
554 XSync( gdi_display, False ); /* flush graphics operations before moving the window */
555 if (is_window_top_level( win ))
557 if (mask & (CWWidth|CWHeight)) set_size_hints( display, win );
558 XReconfigureWMWindow( display, data->whole_window,
559 DefaultScreen(display), mask, &changes );
561 else XConfigureWindow( display, data->whole_window, mask, &changes );
568 /***********************************************************************
569 * X11DRV_sync_client_window_position
571 * Synchronize the X client window position with the Windows one
573 int X11DRV_sync_client_window_position( Display *display, WND *win )
575 XWindowChanges changes;
577 struct x11drv_win_data *data = win->pDriverData;
578 RECT client_rect = win->rectClient;
580 OffsetRect( &client_rect, -data->whole_rect.left, -data->whole_rect.top );
582 if ((mask = get_window_changes( &changes, &data->client_rect, &client_rect )))
584 BOOL was_mapped = is_client_window_mapped( win );
586 TRACE( "setting win %lx pos %d,%d,%dx%d (was %d,%d,%dx%d) after %lx changes=%x\n",
587 data->client_window, client_rect.left, client_rect.top,
588 client_rect.right - client_rect.left, client_rect.bottom - client_rect.top,
589 data->client_rect.left, data->client_rect.top,
590 data->client_rect.right - data->client_rect.left,
591 data->client_rect.bottom - data->client_rect.top,
592 changes.sibling, mask );
593 data->client_rect = client_rect;
595 XSync( gdi_display, False ); /* flush graphics operations before moving the window */
596 if (was_mapped && !is_client_window_mapped( win ))
597 XUnmapWindow( display, data->client_window );
598 XConfigureWindow( display, data->client_window, mask, &changes );
599 if (!was_mapped && is_client_window_mapped( win ))
600 XMapWindow( display, data->client_window );
607 /***********************************************************************
608 * X11DRV_register_window
610 * Associate an X window to a HWND.
612 void X11DRV_register_window( Display *display, HWND hwnd, struct x11drv_win_data *data )
615 XSaveContext( display, data->whole_window, winContext, (char *)hwnd );
616 XSaveContext( display, data->client_window, winContext, (char *)hwnd );
621 /**********************************************************************
624 static void create_desktop( Display *display, WND *wndPtr )
626 X11DRV_WND_DATA *data = wndPtr->pDriverData;
629 winContext = XUniqueContext();
630 wmProtocols = XInternAtom( display, "WM_PROTOCOLS", False );
631 wmDeleteWindow = XInternAtom( display, "WM_DELETE_WINDOW", False );
632 /* wmTakeFocus = XInternAtom( display, "WM_TAKE_FOCUS", False );*/
633 wmTakeFocus = 0; /* not yet */
634 dndProtocol = XInternAtom( display, "DndProtocol" , False );
635 dndSelection = XInternAtom( display, "DndSelection" , False );
636 wmChangeState = XInternAtom (display, "WM_CHANGE_STATE", False);
637 kwmDockWindow = XInternAtom( display, "KWM_DOCKWINDOW", False );
638 _kde_net_wm_system_tray_window_for = XInternAtom( display, "_KDE_NET_WM_SYSTEM_TRAY_WINDOW_FOR", False );
641 data->whole_window = data->client_window = root_window;
643 SetPropA( wndPtr->hwndSelf, "__wine_x11_whole_window", (HANDLE)root_window );
644 SetPropA( wndPtr->hwndSelf, "__wine_x11_client_window", (HANDLE)root_window );
645 SetPropA( wndPtr->hwndSelf, "__wine_x11_visual_id", (HANDLE)XVisualIDFromVisual(visual) );
647 if (root_window != DefaultRootWindow(display)) X11DRV_create_desktop_thread();
651 /**********************************************************************
652 * create_whole_window
654 * Create the whole X window for a given window
656 static Window create_whole_window( Display *display, WND *win )
658 struct x11drv_win_data *data = win->pDriverData;
660 XSetWindowAttributes attr;
663 BOOL is_top_level = is_window_top_level( win );
665 rect = win->rectWindow;
666 X11DRV_window_to_X_rect( win, &rect );
668 if (!(cx = rect.right - rect.left)) cx = 1;
669 if (!(cy = rect.bottom - rect.top)) cy = 1;
671 parent = get_client_window( win->parent );
675 mask = get_window_attributes( display, win, &attr );
677 /* set the attributes that don't change over the lifetime of the window */
678 attr.bit_gravity = ForgetGravity;
679 attr.win_gravity = NorthWestGravity;
680 attr.backing_store = NotUseful/*WhenMapped*/;
681 mask |= CWBitGravity | CWWinGravity | CWBackingStore;
683 data->whole_rect = rect;
684 data->whole_window = XCreateWindow( display, parent, rect.left, rect.top, cx, cy,
685 0, screen_depth, InputOutput, visual,
687 if (attr.cursor) XFreeCursor( display, attr.cursor );
689 if (!data->whole_window) goto done;
691 /* non-maximized child must be at bottom of Z order */
692 if ((win->dwStyle & (WS_CHILD|WS_MAXIMIZE)) == WS_CHILD)
694 XWindowChanges changes;
695 changes.stack_mode = Below;
696 XConfigureWindow( display, data->whole_window, CWStackMode, &changes );
699 if (is_top_level) set_wm_hints( display, win );
703 return data->whole_window;
707 /**********************************************************************
708 * create_client_window
710 * Create the client window for a given window
712 static Window create_client_window( Display *display, WND *win )
714 struct x11drv_win_data *data = win->pDriverData;
715 RECT rect = data->whole_rect;
716 XSetWindowAttributes attr;
718 OffsetRect( &rect, -data->whole_rect.left, -data->whole_rect.top );
719 data->client_rect = rect;
721 attr.event_mask = (ExposureMask | KeyPressMask | KeyReleaseMask | PointerMotionMask |
722 ButtonPressMask | ButtonReleaseMask);
723 attr.bit_gravity = (win->clsStyle & (CS_VREDRAW | CS_HREDRAW)) ?
724 ForgetGravity : NorthWestGravity;
725 attr.backing_store = NotUseful/*WhenMapped*/;
728 data->client_window = XCreateWindow( display, data->whole_window, 0, 0,
729 max( rect.right - rect.left, 1 ),
730 max( rect.bottom - rect.top, 1 ),
733 CWEventMask | CWBitGravity | CWBackingStore, &attr );
734 if (data->client_window && is_client_window_mapped( win ))
735 XMapWindow( display, data->client_window );
737 return data->client_window;
741 /*****************************************************************
742 * SetWindowText (X11DRV.@)
744 BOOL X11DRV_SetWindowText( HWND hwnd, LPCWSTR text )
746 Display *display = thread_display();
749 static UINT text_cp = (UINT)-1;
751 WND *wndPtr = WIN_FindWndPtr( hwnd );
753 if (!wndPtr) return FALSE;
754 if ((win = get_whole_window(wndPtr)))
756 if (text_cp == (UINT)-1)
761 if(!RegOpenKeyA(HKEY_LOCAL_MACHINE, "Software\\Wine\\Wine\\Config\\x11drv", &hkey))
764 DWORD type, count = sizeof(buffer);
765 if(!RegQueryValueExA(hkey, "TextCP", 0, &type, buffer, &count))
766 text_cp = atoi(buffer);
769 TRACE("text_cp = %u\n", text_cp);
772 /* allocate new buffer for window text */
773 count = WideCharToMultiByte(text_cp, 0, text, -1, NULL, 0, NULL, NULL);
774 if (!(buffer = HeapAlloc( GetProcessHeap(), 0, count * sizeof(WCHAR) )))
776 ERR("Not enough memory for window text\n");
777 WIN_ReleaseWndPtr( wndPtr );
780 WideCharToMultiByte(text_cp, 0, text, -1, buffer, count, NULL, NULL);
783 XStoreName( display, win, buffer );
784 XSetIconName( display, win, buffer );
787 HeapFree( GetProcessHeap(), 0, buffer );
789 WIN_ReleaseWndPtr( wndPtr );
794 /***********************************************************************
795 * DestroyWindow (X11DRV.@)
797 BOOL X11DRV_DestroyWindow( HWND hwnd )
799 Display *display = thread_display();
800 WND *wndPtr = WIN_FindWndPtr( hwnd );
801 X11DRV_WND_DATA *data = wndPtr->pDriverData;
803 if (!data) goto done;
805 if (data->whole_window)
807 TRACE( "win %x xwin %lx/%lx\n", hwnd, data->whole_window, data->client_window );
809 XSync( gdi_display, False ); /* flush any reference to this drawable in GDI queue */
810 XDeleteContext( display, data->whole_window, winContext );
811 XDeleteContext( display, data->client_window, winContext );
812 XDestroyWindow( display, data->whole_window ); /* this destroys client too */
813 destroy_icon_window( display, wndPtr );
817 if (data->hWMIconBitmap) DeleteObject( data->hWMIconBitmap );
818 if (data->hWMIconMask) DeleteObject( data->hWMIconMask);
819 HeapFree( GetProcessHeap(), 0, data );
820 wndPtr->pDriverData = NULL;
822 WIN_ReleaseWndPtr( wndPtr );
827 /**********************************************************************
828 * CreateWindow (X11DRV.@)
830 BOOL X11DRV_CreateWindow( HWND hwnd, CREATESTRUCTA *cs, BOOL unicode )
832 Display *display = thread_display();
834 struct x11drv_win_data *data;
838 if (!(data = HeapAlloc(GetProcessHeap(), 0, sizeof(*data)))) return FALSE;
839 data->whole_window = 0;
840 data->client_window = 0;
841 data->icon_window = 0;
842 data->hWMIconBitmap = 0;
843 data->hWMIconMask = 0;
845 wndPtr = WIN_FindWndPtr( hwnd );
846 wndPtr->pDriverData = data;
850 SendMessageW( hwnd, WM_NCCREATE, 0, (LPARAM)cs );
851 create_desktop( display, wndPtr );
852 WIN_ReleaseWndPtr( wndPtr );
856 if (!create_whole_window( display, wndPtr )) goto failed;
857 if (!create_client_window( display, wndPtr )) goto failed;
858 TSXSync( display, False );
860 WIN_ReleaseWndPtr( wndPtr );
862 SetPropA( hwnd, "__wine_x11_whole_window", (HANDLE)data->whole_window );
863 SetPropA( hwnd, "__wine_x11_client_window", (HANDLE)data->client_window );
865 /* send WM_NCCREATE */
866 TRACE( "hwnd %x cs %d,%d %dx%d\n", hwnd, cs->x, cs->y, cs->cx, cs->cy );
868 ret = SendMessageW( hwnd, WM_NCCREATE, 0, (LPARAM)cs );
870 ret = SendMessageA( hwnd, WM_NCCREATE, 0, (LPARAM)cs );
873 X11DRV_DestroyWindow( hwnd );
877 if (!(wndPtr = WIN_FindWndPtr(hwnd))) return FALSE;
879 sync_window_style( display, wndPtr );
881 /* send WM_NCCALCSIZE */
882 rect = wndPtr->rectWindow;
883 SendMessageW( hwnd, WM_NCCALCSIZE, FALSE, (LPARAM)&rect );
884 if (rect.left > rect.right || rect.top > rect.bottom) rect = wndPtr->rectWindow;
885 wndPtr->rectClient = rect;
886 X11DRV_sync_client_window_position( display, wndPtr );
887 X11DRV_register_window( display, hwnd, data );
889 TRACE( "win %x window %d,%d,%d,%d client %d,%d,%d,%d whole %d,%d,%d,%d X client %d,%d,%d,%d xwin %x/%x\n",
890 hwnd, wndPtr->rectWindow.left, wndPtr->rectWindow.top,
891 wndPtr->rectWindow.right, wndPtr->rectWindow.bottom,
892 wndPtr->rectClient.left, wndPtr->rectClient.top,
893 wndPtr->rectClient.right, wndPtr->rectClient.bottom,
894 data->whole_rect.left, data->whole_rect.top,
895 data->whole_rect.right, data->whole_rect.bottom,
896 data->client_rect.left, data->client_rect.top,
897 data->client_rect.right, data->client_rect.bottom,
898 (unsigned int)data->whole_window, (unsigned int)data->client_window );
900 if ((wndPtr->dwStyle & (WS_CHILD|WS_MAXIMIZE)) == WS_CHILD)
901 WIN_LinkWindow( hwnd, HWND_BOTTOM );
903 WIN_LinkWindow( hwnd, HWND_TOP );
905 WIN_ReleaseWndPtr( wndPtr );
908 ret = (SendMessageW( hwnd, WM_CREATE, 0, (LPARAM)cs ) != -1);
910 ret = (SendMessageA( hwnd, WM_CREATE, 0, (LPARAM)cs ) != -1);
914 WIN_UnlinkWindow( hwnd );
915 X11DRV_DestroyWindow( hwnd );
919 /* Send the size messages */
921 if (!(wndPtr = WIN_FindWndPtr(hwnd))) return FALSE;
922 if (!(wndPtr->flags & WIN_NEED_SIZE))
925 if (((wndPtr->rectClient.right-wndPtr->rectClient.left) <0)
926 ||((wndPtr->rectClient.bottom-wndPtr->rectClient.top)<0))
927 WARN("sending bogus WM_SIZE message 0x%08lx\n",
928 MAKELONG(wndPtr->rectClient.right-wndPtr->rectClient.left,
929 wndPtr->rectClient.bottom-wndPtr->rectClient.top));
930 SendMessageW( hwnd, WM_SIZE, SIZE_RESTORED,
931 MAKELONG(wndPtr->rectClient.right-wndPtr->rectClient.left,
932 wndPtr->rectClient.bottom-wndPtr->rectClient.top));
933 SendMessageW( hwnd, WM_MOVE, 0,
934 MAKELONG( wndPtr->rectClient.left, wndPtr->rectClient.top ) );
937 /* Show the window, maximizing or minimizing if needed */
939 if (wndPtr->dwStyle & (WS_MINIMIZE | WS_MAXIMIZE))
941 extern UINT WINPOS_MinMaximize( HWND hwnd, UINT cmd, LPRECT rect ); /*FIXME*/
944 UINT swFlag = (wndPtr->dwStyle & WS_MINIMIZE) ? SW_MINIMIZE : SW_MAXIMIZE;
945 wndPtr->dwStyle &= ~(WS_MAXIMIZE | WS_MINIMIZE);
946 WINPOS_MinMaximize( hwnd, swFlag, &newPos );
947 swFlag = ((wndPtr->dwStyle & WS_CHILD) || GetActiveWindow())
948 ? SWP_NOACTIVATE | SWP_NOZORDER | SWP_FRAMECHANGED
949 : SWP_NOZORDER | SWP_FRAMECHANGED;
950 SetWindowPos( hwnd, 0, newPos.left, newPos.top,
951 newPos.right, newPos.bottom, swFlag );
954 WIN_ReleaseWndPtr( wndPtr );
959 X11DRV_DestroyWindow( wndPtr->hwndSelf );
960 WIN_ReleaseWndPtr( wndPtr );
965 /***********************************************************************
966 * X11DRV_get_client_window
968 * Return the X window associated with the client area of a window
970 Window X11DRV_get_client_window( HWND hwnd )
973 WND *win = WIN_FindWndPtr( hwnd );
976 struct x11drv_win_data *data = win->pDriverData;
977 ret = data->client_window;
978 WIN_ReleaseWndPtr( win );
984 /***********************************************************************
985 * X11DRV_get_whole_window
987 * Return the X window associated with the full area of a window
989 Window X11DRV_get_whole_window( HWND hwnd )
992 WND *win = WIN_FindWndPtr( hwnd );
995 struct x11drv_win_data *data = win->pDriverData;
996 ret = data->whole_window;
997 WIN_ReleaseWndPtr( win );
1003 /***********************************************************************
1004 * X11DRV_get_top_window
1006 * Return the X window associated with the top-level parent of a window
1008 Window X11DRV_get_top_window( HWND hwnd )
1011 WND *win = WIN_FindWndPtr( hwnd );
1012 while (win && win->parent->hwndSelf != GetDesktopWindow())
1013 WIN_UpdateWndPtr( &win, win->parent );
1016 struct x11drv_win_data *data = win->pDriverData;
1017 ret = data->whole_window;
1018 WIN_ReleaseWndPtr( win );
1024 /*****************************************************************
1025 * SetParent (X11DRV.@)
1027 HWND X11DRV_SetParent( HWND hwnd, HWND parent )
1029 Display *display = thread_display();
1035 if (!(wndPtr = WIN_FindWndPtr(hwnd))) return 0;
1037 dwStyle = wndPtr->dwStyle;
1039 if (!parent) parent = GetDesktopWindow();
1041 if (!(pWndParent = WIN_FindWndPtr(parent)))
1043 WIN_ReleaseWndPtr( wndPtr );
1047 /* Windows hides the window first, then shows it again
1048 * including the WM_SHOWWINDOW messages and all */
1049 if (dwStyle & WS_VISIBLE) ShowWindow( hwnd, SW_HIDE );
1051 retvalue = wndPtr->parent->hwndSelf; /* old parent */
1052 if (pWndParent != wndPtr->parent)
1054 struct x11drv_win_data *data = wndPtr->pDriverData;
1056 WIN_UnlinkWindow(wndPtr->hwndSelf);
1057 wndPtr->parent = pWndParent;
1058 WIN_LinkWindow(wndPtr->hwndSelf, HWND_TOP);
1060 if (parent != GetDesktopWindow()) /* a child window */
1062 if (!(wndPtr->dwStyle & WS_CHILD) && wndPtr->wIDmenu)
1064 DestroyMenu( (HMENU)wndPtr->wIDmenu );
1065 wndPtr->wIDmenu = 0;
1070 sync_window_style( display, wndPtr );
1071 if (is_window_top_level( wndPtr )) set_wm_hints( display, wndPtr );
1072 XReparentWindow( display, data->whole_window, get_client_window(pWndParent),
1073 data->whole_rect.left, data->whole_rect.top );
1074 wine_tsx11_unlock();
1076 WIN_ReleaseWndPtr( pWndParent );
1077 WIN_ReleaseWndPtr( wndPtr );
1079 /* SetParent additionally needs to make hwnd the topmost window
1080 in the x-order and send the expected WM_WINDOWPOSCHANGING and
1081 WM_WINDOWPOSCHANGED notification messages.
1083 SetWindowPos( hwnd, HWND_TOPMOST, 0, 0, 0, 0,
1084 SWP_NOACTIVATE|SWP_NOMOVE|SWP_NOSIZE|
1085 ((dwStyle & WS_VISIBLE)?SWP_SHOWWINDOW:0));
1086 /* FIXME: a WM_MOVE is also generated (in the DefWindowProc handler
1087 * for WM_WINDOWPOSCHANGED) in Windows, should probably remove SWP_NOMOVE */
1093 /*******************************************************************
1094 * EnableWindow (X11DRV.@)
1096 BOOL X11DRV_EnableWindow( HWND hwnd, BOOL enable )
1098 Display *display = thread_display();
1103 if (!(wndPtr = WIN_FindWndPtr( hwnd ))) return FALSE;
1105 retvalue = ((wndPtr->dwStyle & WS_DISABLED) != 0);
1107 if (enable && (wndPtr->dwStyle & WS_DISABLED))
1110 wndPtr->dwStyle &= ~WS_DISABLED;
1112 if (wndPtr->dwExStyle & WS_EX_MANAGED)
1115 if (!(wm_hints = XGetWMHints( display, get_whole_window(wndPtr) )))
1116 wm_hints = XAllocWMHints();
1119 wm_hints->flags |= InputHint;
1120 wm_hints->input = TRUE;
1121 XSetWMHints( display, get_whole_window(wndPtr), wm_hints );
1124 wine_tsx11_unlock();
1127 SendMessageA( hwnd, WM_ENABLE, TRUE, 0 );
1129 else if (!enable && !(wndPtr->dwStyle & WS_DISABLED))
1131 SendMessageA( wndPtr->hwndSelf, WM_CANCELMODE, 0, 0 );
1133 /* Disable window */
1134 wndPtr->dwStyle |= WS_DISABLED;
1136 if (wndPtr->dwExStyle & WS_EX_MANAGED)
1139 if (!(wm_hints = XGetWMHints( display, get_whole_window(wndPtr) )))
1140 wm_hints = XAllocWMHints();
1143 wm_hints->flags |= InputHint;
1144 wm_hints->input = FALSE;
1145 XSetWMHints( display, get_whole_window(wndPtr), wm_hints );
1148 wine_tsx11_unlock();
1151 if (hwnd == GetFocus())
1152 SetFocus( 0 ); /* A disabled window can't have the focus */
1154 if (hwnd == GetCapture())
1155 ReleaseCapture(); /* A disabled window can't capture the mouse */
1157 SendMessageA( hwnd, WM_ENABLE, FALSE, 0 );
1159 WIN_ReleaseWndPtr(wndPtr);
1164 /*****************************************************************
1165 * SetFocus (X11DRV.@)
1168 * Explicit colormap management seems to work only with OLVWM.
1170 void X11DRV_SetFocus( HWND hwnd )
1172 Display *display = thread_display();
1173 XWindowAttributes win_attr;
1175 WND *wndPtr = WIN_FindWndPtr( hwnd );
1178 if (!wndPtr) return;
1180 /* Only mess with the X focus if there's */
1181 /* no desktop window and if the window is not managed by the WM. */
1182 if (root_window != DefaultRootWindow(display)) goto done;
1184 while (w && !get_whole_window(w)) w = w->parent;
1186 if (w->dwExStyle & WS_EX_MANAGED) goto done;
1188 if (!hwnd) /* If setting the focus to 0, uninstall the colormap */
1190 if (X11DRV_PALETTE_PaletteFlags & X11DRV_PALETTE_PRIVATE)
1191 TSXUninstallColormap( display, X11DRV_PALETTE_PaletteXColormap );
1193 else if ((win = get_whole_window(w)))
1195 /* Set X focus and install colormap */
1197 if (XGetWindowAttributes( display, win, &win_attr ) &&
1198 (win_attr.map_state == IsViewable))
1200 /* If window is not viewable, don't change anything */
1202 /* we must not use CurrentTime (ICCCM), so try to use last message time instead */
1203 /* FIXME: this is not entirely correct */
1204 XSetInputFocus( display, win, RevertToParent,
1205 /*CurrentTime*/ GetMessageTime() + X11DRV_server_startticks );
1206 if (X11DRV_PALETTE_PaletteFlags & X11DRV_PALETTE_PRIVATE)
1207 XInstallColormap( display, X11DRV_PALETTE_PaletteXColormap );
1209 wine_tsx11_unlock();
1213 WIN_ReleaseWndPtr( wndPtr );
1217 /**********************************************************************
1218 * SetWindowIcon (X11DRV.@)
1220 * hIcon or hIconSm has changed (or is being initialised for the
1221 * first time). Complete the X11 driver-specific initialisation
1222 * and set the window hints.
1224 * This is not entirely correct, may need to create
1225 * an icon window and set the pixmap as a background
1227 HICON X11DRV_SetWindowIcon( HWND hwnd, HICON icon, BOOL small )
1229 Display *display = thread_display();
1230 WND *wndPtr = WIN_FindWndPtr( hwnd );
1231 int index = small ? GCL_HICONSM : GCL_HICON;
1234 if (!wndPtr) return 0;
1236 old = GetClassLongW( hwnd, index );
1237 SetClassLongW( hwnd, index, icon );
1239 SetWindowPos( hwnd, 0, 0, 0, 0, 0, SWP_FRAMECHANGED | SWP_NOSIZE |
1240 SWP_NOMOVE | SWP_NOACTIVATE | SWP_NOZORDER );
1242 if (wndPtr->dwExStyle & WS_EX_MANAGED)
1244 Window win = get_whole_window(wndPtr);
1245 XWMHints* wm_hints = TSXGetWMHints( display, win );
1247 if (!wm_hints) wm_hints = TSXAllocWMHints();
1250 set_icon_hints( display, wndPtr, wm_hints );
1251 TSXSetWMHints( display, win, wm_hints );
1252 TSXFree( wm_hints );
1256 WIN_ReleaseWndPtr( wndPtr );