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 /* X context to associate a hwnd to an X window */
36 XContext winContext
= 0;
38 Atom wmProtocols
= None
;
39 Atom wmDeleteWindow
= None
;
40 Atom wmTakeFocus
= None
;
41 Atom dndProtocol
= None
;
42 Atom dndSelection
= None
;
43 Atom wmChangeState
= None
;
44 Atom kwmDockWindow
= None
;
45 Atom _kde_net_wm_system_tray_window_for
= None
; /* KDE 2 Final */
48 /***********************************************************************
51 * Check if a given window should be managed
53 inline static BOOL
is_window_managed( WND
*win
)
55 if (!Options
.managed
) return FALSE
;
57 /* tray window is always managed */
58 if (win
->dwExStyle
& WS_EX_TRAYWINDOW
) return TRUE
;
59 /* child windows are not managed */
60 if (win
->dwStyle
& WS_CHILD
) return FALSE
;
61 /* tool windows are not managed */
62 if (win
->dwExStyle
& WS_EX_TOOLWINDOW
) return FALSE
;
63 /* windows with caption or thick frame are managed */
64 if ((win
->dwStyle
& WS_CAPTION
) == WS_CAPTION
) return TRUE
;
65 if (win
->dwStyle
& WS_THICKFRAME
) return TRUE
;
66 /* default: not managed */
71 /***********************************************************************
74 * Check if a given window is a top level X11 window
76 inline static BOOL
is_window_top_level( WND
*win
)
78 return (root_window
== DefaultRootWindow(gdi_display
) &&
79 win
->parent
->hwndSelf
== GetDesktopWindow());
83 /***********************************************************************
84 * is_client_window_mapped
86 * Check if the X client window should be mapped
88 inline static BOOL
is_client_window_mapped( WND
*win
)
90 struct x11drv_win_data
*data
= win
->pDriverData
;
91 return !(win
->dwStyle
& WS_MINIMIZE
) && !IsRectEmpty( &data
->client_rect
);
95 /***********************************************************************
96 * get_window_attributes
98 * Fill the window attributes structure for an X window.
99 * Returned cursor must be freed by caller.
101 static int get_window_attributes( Display
*display
, WND
*win
, XSetWindowAttributes
*attr
)
103 BOOL is_top_level
= is_window_top_level( win
);
104 BOOL managed
= is_top_level
&& is_window_managed( win
);
106 if (managed
) win
->dwExStyle
|= WS_EX_MANAGED
;
107 else win
->dwExStyle
&= ~WS_EX_MANAGED
;
109 attr
->override_redirect
= !managed
;
110 attr
->colormap
= X11DRV_PALETTE_PaletteXColormap
;
111 attr
->save_under
= ((win
->clsStyle
& CS_SAVEBITS
) != 0);
113 attr
->event_mask
= (ExposureMask
| KeyPressMask
| KeyReleaseMask
| PointerMotionMask
|
114 ButtonPressMask
| ButtonReleaseMask
);
115 if (is_window_top_level( win
))
117 attr
->event_mask
|= StructureNotifyMask
| FocusChangeMask
;
118 attr
->cursor
= X11DRV_GetCursor( display
, GlobalLock16(GetCursor()) );
120 return (CWOverrideRedirect
| CWSaveUnder
| CWEventMask
| CWColormap
| CWCursor
);
124 /***********************************************************************
127 * Change the X window attributes when the window style has changed.
129 static void sync_window_style( Display
*display
, WND
*win
)
131 XSetWindowAttributes attr
;
135 mask
= get_window_attributes( display
, win
, &attr
);
136 XChangeWindowAttributes( display
, get_whole_window(win
), mask
, &attr
);
137 if (attr
.cursor
) XFreeCursor( display
, attr
.cursor
);
142 /***********************************************************************
145 * fill the window changes structure
147 static int get_window_changes( XWindowChanges
*changes
, const RECT
*old
, const RECT
*new )
151 if (old
->right
- old
->left
!= new->right
- new->left
)
153 if (!(changes
->width
= new->right
- new->left
)) changes
->width
= 1;
156 if (old
->bottom
- old
->top
!= new->bottom
- new->top
)
158 if (!(changes
->height
= new->bottom
- new->top
)) changes
->height
= 1;
161 if (old
->left
!= new->left
)
163 changes
->x
= new->left
;
166 if (old
->top
!= new->top
)
168 changes
->y
= new->top
;
175 /***********************************************************************
178 static Window
create_icon_window( Display
*display
, WND
*win
)
180 struct x11drv_win_data
*data
= win
->pDriverData
;
181 XSetWindowAttributes attr
;
183 attr
.event_mask
= (ExposureMask
| KeyPressMask
| KeyReleaseMask
| PointerMotionMask
|
184 ButtonPressMask
| ButtonReleaseMask
);
185 attr
.bit_gravity
= NorthWestGravity
;
186 attr
.backing_store
= NotUseful
/*WhenMapped*/;
187 attr
.colormap
= X11DRV_PALETTE_PaletteXColormap
; /* Needed due to our visual */
190 data
->icon_window
= XCreateWindow( display
, root_window
, 0, 0,
191 GetSystemMetrics( SM_CXICON
),
192 GetSystemMetrics( SM_CYICON
),
195 CWEventMask
| CWBitGravity
| CWBackingStore
| CWColormap
, &attr
);
196 XSaveContext( display
, data
->icon_window
, winContext
, (char *)win
->hwndSelf
);
199 TRACE( "created %lx\n", data
->icon_window
);
200 SetPropA( win
->hwndSelf
, "__wine_x11_icon_window", (HANDLE
)data
->icon_window
);
201 return data
->icon_window
;
206 /***********************************************************************
207 * destroy_icon_window
209 inline static void destroy_icon_window( Display
*display
, WND
*win
)
211 struct x11drv_win_data
*data
= win
->pDriverData
;
213 if (!data
->icon_window
) return;
215 XDeleteContext( display
, data
->icon_window
, winContext
);
216 XDestroyWindow( display
, data
->icon_window
);
217 data
->icon_window
= 0;
219 RemovePropA( win
->hwndSelf
, "__wine_x11_icon_window" );
223 /***********************************************************************
226 * Set the icon wm hints
228 static void set_icon_hints( Display
*display
, WND
*wndPtr
, XWMHints
*hints
)
230 X11DRV_WND_DATA
*data
= wndPtr
->pDriverData
;
231 HICON hIcon
= GetClassLongA( wndPtr
->hwndSelf
, GCL_HICON
);
233 if (data
->hWMIconBitmap
) DeleteObject( data
->hWMIconBitmap
);
234 if (data
->hWMIconMask
) DeleteObject( data
->hWMIconMask
);
235 data
->hWMIconBitmap
= 0;
236 data
->hWMIconMask
= 0;
238 if (!(wndPtr
->dwExStyle
& WS_EX_MANAGED
))
240 destroy_icon_window( display
, wndPtr
);
241 hints
->flags
&= ~(IconPixmapHint
| IconMaskHint
| IconWindowHint
);
245 if (!data
->icon_window
) create_icon_window( display
, wndPtr
);
246 hints
->icon_window
= data
->icon_window
;
247 hints
->flags
= (hints
->flags
& ~(IconPixmapHint
| IconMaskHint
)) | IconWindowHint
;
257 GetIconInfo(hIcon
, &ii
);
259 X11DRV_CreateBitmap(ii
.hbmMask
);
260 X11DRV_CreateBitmap(ii
.hbmColor
);
262 GetObjectA(ii
.hbmMask
, sizeof(bmMask
), &bmMask
);
265 rcMask
.right
= bmMask
.bmWidth
;
266 rcMask
.bottom
= bmMask
.bmHeight
;
268 hDC
= CreateCompatibleDC(0);
269 hbmOrig
= SelectObject(hDC
, ii
.hbmMask
);
270 InvertRect(hDC
, &rcMask
);
271 SelectObject(hDC
, hbmOrig
);
274 data
->hWMIconBitmap
= ii
.hbmColor
;
275 data
->hWMIconMask
= ii
.hbmMask
;
277 hints
->icon_pixmap
= X11DRV_BITMAP_Pixmap(data
->hWMIconBitmap
);
278 hints
->icon_mask
= X11DRV_BITMAP_Pixmap(data
->hWMIconMask
);
279 destroy_icon_window( display
, wndPtr
);
280 hints
->flags
= (hints
->flags
& ~IconWindowHint
) | IconPixmapHint
| IconMaskHint
;
285 /***********************************************************************
288 * set the window size hints
290 static void set_size_hints( Display
*display
, WND
*win
)
292 XSizeHints
* size_hints
;
293 struct x11drv_win_data
*data
= win
->pDriverData
;
295 if ((size_hints
= XAllocSizeHints()))
297 size_hints
->win_gravity
= StaticGravity
;
298 size_hints
->x
= data
->whole_rect
.left
;
299 size_hints
->y
= data
->whole_rect
.top
;
300 size_hints
->flags
= PWinGravity
| PPosition
;
302 if (HAS_DLGFRAME( win
->dwStyle
, win
->dwExStyle
))
304 size_hints
->max_width
= data
->whole_rect
.right
- data
->whole_rect
.left
;
305 size_hints
->max_height
= data
->whole_rect
.bottom
- data
->whole_rect
.top
;
306 size_hints
->min_width
= size_hints
->max_width
;
307 size_hints
->min_height
= size_hints
->max_height
;
308 size_hints
->flags
|= PMinSize
| PMaxSize
;
310 XSetWMNormalHints( display
, data
->whole_window
, size_hints
);
316 /***********************************************************************
319 * Set the window manager hints for a newly-created window
321 static void set_wm_hints( Display
*display
, WND
*win
)
323 struct x11drv_win_data
*data
= win
->pDriverData
;
325 XClassHint
*class_hints
;
334 protocols
[i
++] = wmDeleteWindow
;
335 if (wmTakeFocus
) protocols
[i
++] = wmTakeFocus
;
336 XSetWMProtocols( display
, data
->whole_window
, protocols
, i
);
339 if ((class_hints
= XAllocClassHint()))
341 class_hints
->res_name
= "wine";
342 class_hints
->res_class
= "Wine";
343 XSetClassHint( display
, data
->whole_window
, class_hints
);
344 XFree( class_hints
);
347 /* transient for hint */
350 Window owner_win
= X11DRV_get_whole_window( win
->owner
);
351 XSetTransientForHint( display
, data
->whole_window
, owner_win
);
352 group_leader
= owner_win
;
354 else group_leader
= data
->whole_window
;
357 set_size_hints( display
, win
);
359 /* systray properties (KDE only for now) */
360 if (win
->dwExStyle
& WS_EX_TRAYWINDOW
)
363 if (kwmDockWindow
!= None
)
364 TSXChangeProperty( display
, data
->whole_window
, kwmDockWindow
, kwmDockWindow
,
365 32, PropModeReplace
, (char*)&val
, 1 );
366 if (_kde_net_wm_system_tray_window_for
!= None
)
367 TSXChangeProperty( display
, data
->whole_window
, _kde_net_wm_system_tray_window_for
,
368 XA_WINDOW
, 32, PropModeReplace
, (char*)&data
->whole_window
, 1 );
374 if ((wm_hints
= TSXAllocWMHints()))
376 wm_hints
->flags
= InputHint
| StateHint
| WindowGroupHint
;
377 /* use globally active model if take focus is supported,
378 * passive model otherwise (cf. ICCCM) */
379 wm_hints
->input
= !wmTakeFocus
;
381 set_icon_hints( display
, win
, wm_hints
);
383 wm_hints
->initial_state
= (win
->dwStyle
& WS_MINIMIZE
) ? IconicState
: NormalState
;
384 wm_hints
->window_group
= group_leader
;
387 XSetWMHints( display
, data
->whole_window
, wm_hints
);
394 /***********************************************************************
395 * X11DRV_set_iconic_state
397 * Set the X11 iconic state according to the window style.
399 void X11DRV_set_iconic_state( WND
*win
)
401 Display
*display
= thread_display();
402 struct x11drv_win_data
*data
= win
->pDriverData
;
404 BOOL iconic
= IsIconic( win
->hwndSelf
);
408 if (iconic
) XUnmapWindow( display
, data
->client_window
);
409 else if (is_client_window_mapped( win
)) XMapWindow( display
, data
->client_window
);
411 if (!(wm_hints
= XGetWMHints( display
, data
->whole_window
))) wm_hints
= XAllocWMHints();
412 wm_hints
->flags
|= StateHint
| IconPositionHint
;
413 wm_hints
->initial_state
= iconic
? IconicState
: NormalState
;
414 wm_hints
->icon_x
= win
->rectWindow
.left
;
415 wm_hints
->icon_y
= win
->rectWindow
.top
;
416 XSetWMHints( display
, data
->whole_window
, wm_hints
);
418 if (win
->dwStyle
& WS_VISIBLE
)
421 XIconifyWindow( display
, data
->whole_window
, DefaultScreen(display
) );
423 if (!IsRectEmpty( &win
->rectWindow
)) XMapWindow( display
, data
->whole_window
);
431 /***********************************************************************
432 * X11DRV_window_to_X_rect
434 * Convert a rect from client to X window coordinates
436 void X11DRV_window_to_X_rect( WND
*win
, RECT
*rect
)
440 if (!(win
->dwExStyle
& WS_EX_MANAGED
)) return;
441 if (IsRectEmpty( rect
)) return;
443 rc
.top
= rc
.bottom
= rc
.left
= rc
.right
= 0;
445 AdjustWindowRectEx( &rc
, win
->dwStyle
& ~(WS_HSCROLL
|WS_VSCROLL
), FALSE
, win
->dwExStyle
);
447 rect
->left
-= rc
.left
;
448 rect
->right
-= rc
.right
;
450 rect
->bottom
-= rc
.bottom
;
451 if (rect
->top
>= rect
->bottom
) rect
->bottom
= rect
->top
+ 1;
452 if (rect
->left
>= rect
->right
) rect
->right
= rect
->left
+ 1;
456 /***********************************************************************
457 * X11DRV_X_to_window_rect
459 * Opposite of X11DRV_window_to_X_rect
461 void X11DRV_X_to_window_rect( WND
*win
, RECT
*rect
)
463 if (!(win
->dwExStyle
& WS_EX_MANAGED
)) return;
464 if (IsRectEmpty( rect
)) return;
466 AdjustWindowRectEx( rect
, win
->dwStyle
& ~(WS_HSCROLL
|WS_VSCROLL
), FALSE
, win
->dwExStyle
);
468 if (rect
->top
>= rect
->bottom
) rect
->bottom
= rect
->top
+ 1;
469 if (rect
->left
>= rect
->right
) rect
->right
= rect
->left
+ 1;
473 /***********************************************************************
474 * X11DRV_sync_whole_window_position
476 * Synchronize the X whole window position with the Windows one
478 int X11DRV_sync_whole_window_position( Display
*display
, WND
*win
, int zorder
)
480 XWindowChanges changes
;
482 struct x11drv_win_data
*data
= win
->pDriverData
;
483 RECT whole_rect
= win
->rectWindow
;
485 X11DRV_window_to_X_rect( win
, &whole_rect
);
486 mask
= get_window_changes( &changes
, &data
->whole_rect
, &whole_rect
);
490 /* find window that this one must be after */
491 HWND prev
= GetWindow( win
->hwndSelf
, GW_HWNDPREV
);
492 if (!prev
) /* top child */
494 changes
.stack_mode
= Above
;
499 changes
.stack_mode
= Below
;
500 changes
.sibling
= X11DRV_get_whole_window(prev
);
501 mask
|= CWStackMode
| CWSibling
;
505 data
->whole_rect
= whole_rect
;
509 TRACE( "setting win %lx pos %d,%d,%dx%d after %lx changes=%x\n",
510 data
->whole_window
, whole_rect
.left
, whole_rect
.top
,
511 whole_rect
.right
- whole_rect
.left
, whole_rect
.bottom
- whole_rect
.top
,
512 changes
.sibling
, mask
);
514 XSync( gdi_display
, False
); /* flush graphics operations before moving the window */
515 if (is_window_top_level( win
))
517 if (mask
& (CWWidth
|CWHeight
)) set_size_hints( display
, win
);
518 XReconfigureWMWindow( display
, data
->whole_window
,
519 DefaultScreen(display
), mask
, &changes
);
521 else XConfigureWindow( display
, data
->whole_window
, mask
, &changes
);
528 /***********************************************************************
529 * X11DRV_sync_client_window_position
531 * Synchronize the X client window position with the Windows one
533 int X11DRV_sync_client_window_position( Display
*display
, WND
*win
)
535 XWindowChanges changes
;
537 struct x11drv_win_data
*data
= win
->pDriverData
;
538 RECT client_rect
= win
->rectClient
;
540 OffsetRect( &client_rect
, -data
->whole_rect
.left
, -data
->whole_rect
.top
);
542 if ((mask
= get_window_changes( &changes
, &data
->client_rect
, &client_rect
)))
544 BOOL was_mapped
= is_client_window_mapped( win
);
546 TRACE( "setting win %lx pos %d,%d,%dx%d (was %d,%d,%dx%d) after %lx changes=%x\n",
547 data
->client_window
, client_rect
.left
, client_rect
.top
,
548 client_rect
.right
- client_rect
.left
, client_rect
.bottom
- client_rect
.top
,
549 data
->client_rect
.left
, data
->client_rect
.top
,
550 data
->client_rect
.right
- data
->client_rect
.left
,
551 data
->client_rect
.bottom
- data
->client_rect
.top
,
552 changes
.sibling
, mask
);
553 data
->client_rect
= client_rect
;
555 XSync( gdi_display
, False
); /* flush graphics operations before moving the window */
556 if (was_mapped
&& !is_client_window_mapped( win
))
557 XUnmapWindow( display
, data
->client_window
);
558 XConfigureWindow( display
, data
->client_window
, mask
, &changes
);
559 if (!was_mapped
&& is_client_window_mapped( win
))
560 XMapWindow( display
, data
->client_window
);
567 /***********************************************************************
568 * X11DRV_register_window
570 * Associate an X window to a HWND.
572 void X11DRV_register_window( Display
*display
, HWND hwnd
, struct x11drv_win_data
*data
)
575 XSaveContext( display
, data
->whole_window
, winContext
, (char *)hwnd
);
576 XSaveContext( display
, data
->client_window
, winContext
, (char *)hwnd
);
581 /**********************************************************************
584 static void create_desktop( Display
*display
, WND
*wndPtr
, CREATESTRUCTA
*cs
)
586 X11DRV_WND_DATA
*data
= wndPtr
->pDriverData
;
589 winContext
= XUniqueContext();
590 wmProtocols
= XInternAtom( display
, "WM_PROTOCOLS", False
);
591 wmDeleteWindow
= XInternAtom( display
, "WM_DELETE_WINDOW", False
);
592 /* wmTakeFocus = XInternAtom( display, "WM_TAKE_FOCUS", False );*/
593 wmTakeFocus
= 0; /* not yet */
594 dndProtocol
= XInternAtom( display
, "DndProtocol" , False
);
595 dndSelection
= XInternAtom( display
, "DndSelection" , False
);
596 wmChangeState
= XInternAtom (display
, "WM_CHANGE_STATE", False
);
597 kwmDockWindow
= XInternAtom( display
, "KWM_DOCKWINDOW", False
);
598 _kde_net_wm_system_tray_window_for
= XInternAtom( display
, "_KDE_NET_WM_SYSTEM_TRAY_WINDOW_FOR", False
);
601 data
->whole_window
= data
->client_window
= root_window
;
602 data
->whole_rect
= data
->client_rect
= wndPtr
->rectWindow
;
604 SetPropA( wndPtr
->hwndSelf
, "__wine_x11_whole_window", (HANDLE
)root_window
);
605 SetPropA( wndPtr
->hwndSelf
, "__wine_x11_client_window", (HANDLE
)root_window
);
606 SetPropA( wndPtr
->hwndSelf
, "__wine_x11_visual_id", (HANDLE
)XVisualIDFromVisual(visual
) );
608 SendMessageW( wndPtr
->hwndSelf
, WM_NCCREATE
, 0, (LPARAM
)cs
);
609 if (root_window
!= DefaultRootWindow(display
)) X11DRV_create_desktop_thread();
613 /**********************************************************************
614 * create_whole_window
616 * Create the whole X window for a given window
618 static Window
create_whole_window( Display
*display
, WND
*win
)
620 struct x11drv_win_data
*data
= win
->pDriverData
;
622 XSetWindowAttributes attr
;
625 BOOL is_top_level
= is_window_top_level( win
);
627 rect
= win
->rectWindow
;
628 X11DRV_window_to_X_rect( win
, &rect
);
630 if (!(cx
= rect
.right
- rect
.left
)) cx
= 1;
631 if (!(cy
= rect
.bottom
- rect
.top
)) cy
= 1;
633 parent
= get_client_window( win
->parent
);
637 mask
= get_window_attributes( display
, win
, &attr
);
639 /* set the attributes that don't change over the lifetime of the window */
640 attr
.bit_gravity
= ForgetGravity
;
641 attr
.win_gravity
= NorthWestGravity
;
642 attr
.backing_store
= NotUseful
/*WhenMapped*/;
643 mask
|= CWBitGravity
| CWWinGravity
| CWBackingStore
;
645 data
->whole_rect
= rect
;
646 data
->whole_window
= XCreateWindow( display
, parent
, rect
.left
, rect
.top
, cx
, cy
,
647 0, screen_depth
, InputOutput
, visual
,
649 if (attr
.cursor
) XFreeCursor( display
, attr
.cursor
);
651 if (!data
->whole_window
)
657 /* non-maximized child must be at bottom of Z order */
658 if ((win
->dwStyle
& (WS_CHILD
|WS_MAXIMIZE
)) == WS_CHILD
)
660 XWindowChanges changes
;
661 changes
.stack_mode
= Below
;
662 XConfigureWindow( display
, data
->whole_window
, CWStackMode
, &changes
);
667 if (is_top_level
) set_wm_hints( display
, win
);
669 return data
->whole_window
;
673 /**********************************************************************
674 * create_client_window
676 * Create the client window for a given window
678 static Window
create_client_window( Display
*display
, WND
*win
)
680 struct x11drv_win_data
*data
= win
->pDriverData
;
681 RECT rect
= data
->whole_rect
;
682 XSetWindowAttributes attr
;
684 OffsetRect( &rect
, -data
->whole_rect
.left
, -data
->whole_rect
.top
);
685 data
->client_rect
= rect
;
687 attr
.event_mask
= (ExposureMask
| KeyPressMask
| KeyReleaseMask
| PointerMotionMask
|
688 ButtonPressMask
| ButtonReleaseMask
);
689 attr
.bit_gravity
= (win
->clsStyle
& (CS_VREDRAW
| CS_HREDRAW
)) ?
690 ForgetGravity
: NorthWestGravity
;
691 attr
.backing_store
= NotUseful
/*WhenMapped*/;
694 data
->client_window
= XCreateWindow( display
, data
->whole_window
, 0, 0,
695 max( rect
.right
- rect
.left
, 1 ),
696 max( rect
.bottom
- rect
.top
, 1 ),
699 CWEventMask
| CWBitGravity
| CWBackingStore
, &attr
);
700 if (data
->client_window
&& is_client_window_mapped( win
))
701 XMapWindow( display
, data
->client_window
);
703 return data
->client_window
;
707 /*****************************************************************
708 * SetWindowText (X11DRV.@)
710 BOOL
X11DRV_SetWindowText( HWND hwnd
, LPCWSTR text
)
712 Display
*display
= thread_display();
715 static UINT text_cp
= (UINT
)-1;
717 WND
*wndPtr
= WIN_FindWndPtr( hwnd
);
719 if (!wndPtr
) return FALSE
;
720 if ((win
= get_whole_window(wndPtr
)))
722 if (text_cp
== (UINT
)-1)
727 if(!RegOpenKeyA(HKEY_LOCAL_MACHINE
, "Software\\Wine\\Wine\\Config\\x11drv", &hkey
))
730 DWORD type
, count
= sizeof(buffer
);
731 if(!RegQueryValueExA(hkey
, "TextCP", 0, &type
, buffer
, &count
))
732 text_cp
= atoi(buffer
);
735 TRACE("text_cp = %u\n", text_cp
);
738 /* allocate new buffer for window text */
739 count
= WideCharToMultiByte(text_cp
, 0, text
, -1, NULL
, 0, NULL
, NULL
);
740 if (!(buffer
= HeapAlloc( GetProcessHeap(), 0, count
)))
742 ERR("Not enough memory for window text\n");
743 WIN_ReleaseWndPtr( wndPtr
);
746 WideCharToMultiByte(text_cp
, 0, text
, -1, buffer
, count
, NULL
, NULL
);
749 XStoreName( display
, win
, buffer
);
750 XSetIconName( display
, win
, buffer
);
753 HeapFree( GetProcessHeap(), 0, buffer
);
755 WIN_ReleaseWndPtr( wndPtr
);
760 /***********************************************************************
761 * DestroyWindow (X11DRV.@)
763 BOOL
X11DRV_DestroyWindow( HWND hwnd
)
765 Display
*display
= thread_display();
766 WND
*wndPtr
= WIN_FindWndPtr( hwnd
);
767 X11DRV_WND_DATA
*data
= wndPtr
->pDriverData
;
769 if (!data
) goto done
;
771 if (data
->whole_window
)
773 TRACE( "win %x xwin %lx/%lx\n", hwnd
, data
->whole_window
, data
->client_window
);
775 XSync( gdi_display
, False
); /* flush any reference to this drawable in GDI queue */
776 XDeleteContext( display
, data
->whole_window
, winContext
);
777 XDeleteContext( display
, data
->client_window
, winContext
);
778 XDestroyWindow( display
, data
->whole_window
); /* this destroys client too */
779 destroy_icon_window( display
, wndPtr
);
783 if (data
->hWMIconBitmap
) DeleteObject( data
->hWMIconBitmap
);
784 if (data
->hWMIconMask
) DeleteObject( data
->hWMIconMask
);
785 HeapFree( GetProcessHeap(), 0, data
);
786 wndPtr
->pDriverData
= NULL
;
788 WIN_ReleaseWndPtr( wndPtr
);
793 /**********************************************************************
794 * CreateWindow (X11DRV.@)
796 BOOL
X11DRV_CreateWindow( HWND hwnd
, CREATESTRUCTA
*cs
, BOOL unicode
)
798 Display
*display
= thread_display();
800 struct x11drv_win_data
*data
;
804 if (!(data
= HeapAlloc(GetProcessHeap(), 0, sizeof(*data
)))) return FALSE
;
805 data
->whole_window
= 0;
806 data
->client_window
= 0;
807 data
->icon_window
= 0;
808 data
->hWMIconBitmap
= 0;
809 data
->hWMIconMask
= 0;
811 wndPtr
= WIN_FindWndPtr( hwnd
);
812 wndPtr
->pDriverData
= data
;
816 create_desktop( display
, wndPtr
, cs
);
817 WIN_ReleaseWndPtr( wndPtr
);
821 if (!create_whole_window( display
, wndPtr
)) goto failed
;
822 if (!create_client_window( display
, wndPtr
)) goto failed
;
823 TSXSync( display
, False
);
825 WIN_ReleaseWndPtr( wndPtr
);
827 SetPropA( hwnd
, "__wine_x11_whole_window", (HANDLE
)data
->whole_window
);
828 SetPropA( hwnd
, "__wine_x11_client_window", (HANDLE
)data
->client_window
);
830 /* send WM_NCCREATE */
831 TRACE( "hwnd %x cs %d,%d %dx%d\n", hwnd
, cs
->x
, cs
->y
, cs
->cx
, cs
->cy
);
833 ret
= SendMessageW( hwnd
, WM_NCCREATE
, 0, (LPARAM
)cs
);
835 ret
= SendMessageA( hwnd
, WM_NCCREATE
, 0, (LPARAM
)cs
);
838 X11DRV_DestroyWindow( hwnd
);
842 if (!(wndPtr
= WIN_FindWndPtr(hwnd
))) return FALSE
;
844 sync_window_style( display
, wndPtr
);
846 /* send WM_NCCALCSIZE */
847 rect
= wndPtr
->rectWindow
;
848 SendMessageW( hwnd
, WM_NCCALCSIZE
, FALSE
, (LPARAM
)&rect
);
849 if (rect
.left
> rect
.right
|| rect
.top
> rect
.bottom
) rect
= wndPtr
->rectWindow
;
850 wndPtr
->rectClient
= rect
;
851 X11DRV_sync_client_window_position( display
, wndPtr
);
852 X11DRV_register_window( display
, hwnd
, data
);
854 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",
855 hwnd
, wndPtr
->rectWindow
.left
, wndPtr
->rectWindow
.top
,
856 wndPtr
->rectWindow
.right
, wndPtr
->rectWindow
.bottom
,
857 wndPtr
->rectClient
.left
, wndPtr
->rectClient
.top
,
858 wndPtr
->rectClient
.right
, wndPtr
->rectClient
.bottom
,
859 data
->whole_rect
.left
, data
->whole_rect
.top
,
860 data
->whole_rect
.right
, data
->whole_rect
.bottom
,
861 data
->client_rect
.left
, data
->client_rect
.top
,
862 data
->client_rect
.right
, data
->client_rect
.bottom
,
863 (unsigned int)data
->whole_window
, (unsigned int)data
->client_window
);
865 if ((wndPtr
->dwStyle
& (WS_CHILD
|WS_MAXIMIZE
)) == WS_CHILD
)
866 WIN_LinkWindow( hwnd
, HWND_BOTTOM
);
868 WIN_LinkWindow( hwnd
, HWND_TOP
);
870 WIN_ReleaseWndPtr( wndPtr
);
873 ret
= (SendMessageW( hwnd
, WM_CREATE
, 0, (LPARAM
)cs
) != -1);
875 ret
= (SendMessageA( hwnd
, WM_CREATE
, 0, (LPARAM
)cs
) != -1);
879 WIN_UnlinkWindow( hwnd
);
880 X11DRV_DestroyWindow( hwnd
);
884 /* Send the size messages */
886 if (!(wndPtr
= WIN_FindWndPtr(hwnd
))) return FALSE
;
887 if (!(wndPtr
->flags
& WIN_NEED_SIZE
))
890 if (((wndPtr
->rectClient
.right
-wndPtr
->rectClient
.left
) <0)
891 ||((wndPtr
->rectClient
.bottom
-wndPtr
->rectClient
.top
)<0))
892 WARN("sending bogus WM_SIZE message 0x%08lx\n",
893 MAKELONG(wndPtr
->rectClient
.right
-wndPtr
->rectClient
.left
,
894 wndPtr
->rectClient
.bottom
-wndPtr
->rectClient
.top
));
895 SendMessageW( hwnd
, WM_SIZE
, SIZE_RESTORED
,
896 MAKELONG(wndPtr
->rectClient
.right
-wndPtr
->rectClient
.left
,
897 wndPtr
->rectClient
.bottom
-wndPtr
->rectClient
.top
));
898 SendMessageW( hwnd
, WM_MOVE
, 0,
899 MAKELONG( wndPtr
->rectClient
.left
, wndPtr
->rectClient
.top
) );
902 /* Show the window, maximizing or minimizing if needed */
904 if (wndPtr
->dwStyle
& (WS_MINIMIZE
| WS_MAXIMIZE
))
906 extern UINT
WINPOS_MinMaximize( HWND hwnd
, UINT cmd
, LPRECT rect
); /*FIXME*/
909 UINT swFlag
= (wndPtr
->dwStyle
& WS_MINIMIZE
) ? SW_MINIMIZE
: SW_MAXIMIZE
;
910 wndPtr
->dwStyle
&= ~(WS_MAXIMIZE
| WS_MINIMIZE
);
911 WINPOS_MinMaximize( hwnd
, swFlag
, &newPos
);
912 swFlag
= ((wndPtr
->dwStyle
& WS_CHILD
) || GetActiveWindow())
913 ? SWP_NOACTIVATE
| SWP_NOZORDER
| SWP_FRAMECHANGED
914 : SWP_NOZORDER
| SWP_FRAMECHANGED
;
915 SetWindowPos( hwnd
, 0, newPos
.left
, newPos
.top
,
916 newPos
.right
, newPos
.bottom
, swFlag
);
919 WIN_ReleaseWndPtr( wndPtr
);
924 X11DRV_DestroyWindow( wndPtr
->hwndSelf
);
925 WIN_ReleaseWndPtr( wndPtr
);
930 /***********************************************************************
931 * X11DRV_get_client_window
933 * Return the X window associated with the client area of a window
935 Window
X11DRV_get_client_window( HWND hwnd
)
938 WND
*win
= WIN_FindWndPtr( hwnd
);
941 struct x11drv_win_data
*data
= win
->pDriverData
;
942 ret
= data
->client_window
;
943 WIN_ReleaseWndPtr( win
);
949 /***********************************************************************
950 * X11DRV_get_whole_window
952 * Return the X window associated with the full area of a window
954 Window
X11DRV_get_whole_window( HWND hwnd
)
957 WND
*win
= WIN_FindWndPtr( hwnd
);
960 struct x11drv_win_data
*data
= win
->pDriverData
;
961 ret
= data
->whole_window
;
962 WIN_ReleaseWndPtr( win
);
968 /*****************************************************************
969 * SetParent (X11DRV.@)
971 HWND
X11DRV_SetParent( HWND hwnd
, HWND parent
)
973 Display
*display
= thread_display();
979 if (!(wndPtr
= WIN_FindWndPtr(hwnd
))) return 0;
981 dwStyle
= wndPtr
->dwStyle
;
983 if (!parent
) parent
= GetDesktopWindow();
985 if (!(pWndParent
= WIN_FindWndPtr(parent
)))
987 WIN_ReleaseWndPtr( wndPtr
);
991 /* Windows hides the window first, then shows it again
992 * including the WM_SHOWWINDOW messages and all */
993 if (dwStyle
& WS_VISIBLE
) ShowWindow( hwnd
, SW_HIDE
);
995 retvalue
= wndPtr
->parent
->hwndSelf
; /* old parent */
996 if (pWndParent
!= wndPtr
->parent
)
998 struct x11drv_win_data
*data
= wndPtr
->pDriverData
;
1000 WIN_UnlinkWindow(wndPtr
->hwndSelf
);
1001 wndPtr
->parent
= pWndParent
;
1002 WIN_LinkWindow(wndPtr
->hwndSelf
, HWND_TOP
);
1004 if (parent
!= GetDesktopWindow()) /* a child window */
1006 if (!(wndPtr
->dwStyle
& WS_CHILD
) && wndPtr
->wIDmenu
)
1008 DestroyMenu( (HMENU
)wndPtr
->wIDmenu
);
1009 wndPtr
->wIDmenu
= 0;
1013 if (is_window_top_level( wndPtr
)) set_wm_hints( display
, wndPtr
);
1015 sync_window_style( display
, wndPtr
);
1016 XReparentWindow( display
, data
->whole_window
, get_client_window(pWndParent
),
1017 data
->whole_rect
.left
, data
->whole_rect
.top
);
1018 wine_tsx11_unlock();
1020 WIN_ReleaseWndPtr( pWndParent
);
1021 WIN_ReleaseWndPtr( wndPtr
);
1023 /* SetParent additionally needs to make hwnd the topmost window
1024 in the x-order and send the expected WM_WINDOWPOSCHANGING and
1025 WM_WINDOWPOSCHANGED notification messages.
1027 SetWindowPos( hwnd
, HWND_TOPMOST
, 0, 0, 0, 0,
1028 SWP_NOACTIVATE
|SWP_NOMOVE
|SWP_NOSIZE
|
1029 ((dwStyle
& WS_VISIBLE
)?SWP_SHOWWINDOW
:0));
1030 /* FIXME: a WM_MOVE is also generated (in the DefWindowProc handler
1031 * for WM_WINDOWPOSCHANGED) in Windows, should probably remove SWP_NOMOVE */
1037 /*******************************************************************
1038 * EnableWindow (X11DRV.@)
1040 BOOL
X11DRV_EnableWindow( HWND hwnd
, BOOL enable
)
1042 Display
*display
= thread_display();
1047 if (!(wndPtr
= WIN_FindWndPtr( hwnd
))) return FALSE
;
1049 retvalue
= ((wndPtr
->dwStyle
& WS_DISABLED
) != 0);
1051 if (enable
&& (wndPtr
->dwStyle
& WS_DISABLED
))
1054 wndPtr
->dwStyle
&= ~WS_DISABLED
;
1056 if (wndPtr
->dwExStyle
& WS_EX_MANAGED
)
1059 if (!(wm_hints
= XGetWMHints( display
, get_whole_window(wndPtr
) )))
1060 wm_hints
= XAllocWMHints();
1063 wm_hints
->flags
|= InputHint
;
1064 wm_hints
->input
= TRUE
;
1065 XSetWMHints( display
, get_whole_window(wndPtr
), wm_hints
);
1068 wine_tsx11_unlock();
1071 SendMessageA( hwnd
, WM_ENABLE
, TRUE
, 0 );
1073 else if (!enable
&& !(wndPtr
->dwStyle
& WS_DISABLED
))
1075 SendMessageA( wndPtr
->hwndSelf
, WM_CANCELMODE
, 0, 0 );
1077 /* Disable window */
1078 wndPtr
->dwStyle
|= WS_DISABLED
;
1080 if (wndPtr
->dwExStyle
& WS_EX_MANAGED
)
1083 if (!(wm_hints
= XGetWMHints( display
, get_whole_window(wndPtr
) )))
1084 wm_hints
= XAllocWMHints();
1087 wm_hints
->flags
|= InputHint
;
1088 wm_hints
->input
= FALSE
;
1089 XSetWMHints( display
, get_whole_window(wndPtr
), wm_hints
);
1092 wine_tsx11_unlock();
1095 if (hwnd
== GetFocus())
1096 SetFocus( 0 ); /* A disabled window can't have the focus */
1098 if (hwnd
== GetCapture())
1099 ReleaseCapture(); /* A disabled window can't capture the mouse */
1101 SendMessageA( hwnd
, WM_ENABLE
, FALSE
, 0 );
1103 WIN_ReleaseWndPtr(wndPtr
);
1108 /*****************************************************************
1109 * SetFocus (X11DRV.@)
1112 * Explicit colormap management seems to work only with OLVWM.
1114 void X11DRV_SetFocus( HWND hwnd
)
1116 Display
*display
= thread_display();
1117 XWindowAttributes win_attr
;
1120 /* Only mess with the X focus if there's */
1121 /* no desktop window and if the window is not managed by the WM. */
1122 if (root_window
!= DefaultRootWindow(display
)) return;
1124 if (!hwnd
) /* If setting the focus to 0, uninstall the colormap */
1126 if (X11DRV_PALETTE_PaletteFlags
& X11DRV_PALETTE_PRIVATE
)
1127 TSXUninstallColormap( display
, X11DRV_PALETTE_PaletteXColormap
);
1131 hwnd
= GetAncestor( hwnd
, GA_ROOT
);
1132 if (GetWindowLongW( hwnd
, GWL_EXSTYLE
) & WS_EX_MANAGED
) return;
1133 if (!(win
= X11DRV_get_whole_window( hwnd
))) return;
1135 /* Set X focus and install colormap */
1137 if (XGetWindowAttributes( display
, win
, &win_attr
) &&
1138 (win_attr
.map_state
== IsViewable
))
1140 /* If window is not viewable, don't change anything */
1142 /* we must not use CurrentTime (ICCCM), so try to use last message time instead */
1143 /* FIXME: this is not entirely correct */
1144 XSetInputFocus( display
, win
, RevertToParent
,
1145 /*CurrentTime*/ GetMessageTime() + X11DRV_server_startticks
);
1146 if (X11DRV_PALETTE_PaletteFlags
& X11DRV_PALETTE_PRIVATE
)
1147 XInstallColormap( display
, X11DRV_PALETTE_PaletteXColormap
);
1149 wine_tsx11_unlock();
1153 /**********************************************************************
1154 * SetWindowIcon (X11DRV.@)
1156 * hIcon or hIconSm has changed (or is being initialised for the
1157 * first time). Complete the X11 driver-specific initialisation
1158 * and set the window hints.
1160 * This is not entirely correct, may need to create
1161 * an icon window and set the pixmap as a background
1163 HICON
X11DRV_SetWindowIcon( HWND hwnd
, HICON icon
, BOOL small
)
1165 Display
*display
= thread_display();
1166 WND
*wndPtr
= WIN_FindWndPtr( hwnd
);
1167 int index
= small
? GCL_HICONSM
: GCL_HICON
;
1170 if (!wndPtr
) return 0;
1172 old
= GetClassLongW( hwnd
, index
);
1173 SetClassLongW( hwnd
, index
, icon
);
1175 SetWindowPos( hwnd
, 0, 0, 0, 0, 0, SWP_FRAMECHANGED
| SWP_NOSIZE
|
1176 SWP_NOMOVE
| SWP_NOACTIVATE
| SWP_NOZORDER
);
1178 if (wndPtr
->dwExStyle
& WS_EX_MANAGED
)
1180 Window win
= get_whole_window(wndPtr
);
1181 XWMHints
* wm_hints
= TSXGetWMHints( display
, win
);
1183 if (!wm_hints
) wm_hints
= TSXAllocWMHints();
1186 set_icon_hints( display
, wndPtr
, wm_hints
);
1187 TSXSetWMHints( display
, win
, wm_hints
);
1188 TSXFree( wm_hints
);
1192 WIN_ReleaseWndPtr( wndPtr
);