2 * Window related functions
4 * Copyright 1993, 1994, 1995, 1996, 2001 Alexandre Julliard
5 * Copyright 1993 David Metcalfe
6 * Copyright 1995, 1996 Alex Korobka
8 * This library is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU Lesser General Public
10 * License as published by the Free Software Foundation; either
11 * version 2.1 of the License, or (at your option) any later version.
13 * This library is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 * Lesser General Public License for more details.
18 * You should have received a copy of the GNU Lesser General Public
19 * License along with this library; if not, write to the Free Software
20 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
28 #include <X11/Xresource.h>
29 #include <X11/Xutil.h>
35 #include "wine/unicode.h"
37 #include "wine/debug.h"
43 WINE_DEFAULT_DEBUG_CHANNEL(x11drv
);
45 extern Pixmap
X11DRV_BITMAP_Pixmap( HBITMAP
);
47 #define HAS_DLGFRAME(style,exStyle) \
48 (((exStyle) & WS_EX_DLGMODALFRAME) || \
49 (((style) & WS_DLGFRAME) && !((style) & WS_THICKFRAME)))
51 /* X context to associate a hwnd to an X window */
52 XContext winContext
= 0;
54 Atom wmProtocols
= None
;
55 Atom wmDeleteWindow
= None
;
56 Atom wmTakeFocus
= None
;
57 Atom dndProtocol
= None
;
58 Atom dndSelection
= None
;
59 Atom wmChangeState
= None
;
61 Atom kwmDockWindow
= None
;
62 Atom _kde_net_wm_system_tray_window_for
= None
; /* KDE 2 Final */
64 static LPCSTR whole_window_atom
;
65 static LPCSTR client_window_atom
;
66 static LPCSTR icon_window_atom
;
68 /***********************************************************************
71 * Check if a given window should be managed
73 inline static BOOL
is_window_managed( WND
*win
)
75 if (!managed_mode
) return FALSE
;
76 /* tray window is always managed */
77 if (win
->dwExStyle
& WS_EX_TRAYWINDOW
) return TRUE
;
78 /* child windows are not managed */
79 if (win
->dwStyle
& WS_CHILD
) return FALSE
;
80 /* tool windows are not managed */
81 if (win
->dwExStyle
& WS_EX_TOOLWINDOW
) return FALSE
;
82 /* windows with caption or thick frame are managed */
83 if ((win
->dwStyle
& WS_CAPTION
) == WS_CAPTION
) return TRUE
;
84 if (win
->dwStyle
& WS_THICKFRAME
) return TRUE
;
85 /* default: not managed */
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 !(win
->dwStyle
& WS_MINIMIZE
) && !IsRectEmpty( &data
->client_rect
);
102 /***********************************************************************
103 * get_window_attributes
105 * Fill the window attributes structure for an X window.
107 static int get_window_attributes( Display
*display
, WND
*win
, XSetWindowAttributes
*attr
)
109 BOOL is_top_level
= is_window_top_level( win
);
110 BOOL managed
= is_top_level
&& is_window_managed( win
);
112 if (managed
) WIN_SetExStyle( win
->hwndSelf
, win
->dwExStyle
| WS_EX_MANAGED
);
113 else WIN_SetExStyle( win
->hwndSelf
, win
->dwExStyle
& ~WS_EX_MANAGED
);
115 attr
->override_redirect
= !managed
;
116 attr
->colormap
= X11DRV_PALETTE_PaletteXColormap
;
117 attr
->save_under
= ((win
->clsStyle
& CS_SAVEBITS
) != 0);
118 attr
->cursor
= x11drv_thread_data()->cursor
;
119 attr
->event_mask
= (ExposureMask
| PointerMotionMask
|
120 ButtonPressMask
| ButtonReleaseMask
| EnterWindowMask
);
122 if (is_window_top_level( win
))
123 attr
->event_mask
|= (KeyPressMask
| KeyReleaseMask
| StructureNotifyMask
|
124 FocusChangeMask
| KeymapStateMask
);
126 return (CWOverrideRedirect
| CWSaveUnder
| CWEventMask
| CWColormap
| CWCursor
);
130 /***********************************************************************
131 * X11DRV_sync_window_style
133 * Change the X window attributes when the window style has changed.
135 void X11DRV_sync_window_style( Display
*display
, WND
*win
)
137 XSetWindowAttributes attr
;
141 mask
= get_window_attributes( display
, win
, &attr
);
142 XChangeWindowAttributes( display
, get_whole_window(win
), mask
, &attr
);
147 /***********************************************************************
150 * fill the window changes structure
152 static int get_window_changes( XWindowChanges
*changes
, const RECT
*old
, const RECT
*new )
156 if (old
->right
- old
->left
!= new->right
- new->left
)
158 if (!(changes
->width
= new->right
- new->left
)) changes
->width
= 1;
161 if (old
->bottom
- old
->top
!= new->bottom
- new->top
)
163 if (!(changes
->height
= new->bottom
- new->top
)) changes
->height
= 1;
166 if (old
->left
!= new->left
)
168 changes
->x
= new->left
;
171 if (old
->top
!= new->top
)
173 changes
->y
= new->top
;
180 /***********************************************************************
183 static Window
create_icon_window( Display
*display
, WND
*win
)
185 struct x11drv_win_data
*data
= win
->pDriverData
;
186 XSetWindowAttributes attr
;
188 attr
.event_mask
= (ExposureMask
| KeyPressMask
| KeyReleaseMask
| PointerMotionMask
|
189 ButtonPressMask
| ButtonReleaseMask
| EnterWindowMask
);
190 attr
.bit_gravity
= NorthWestGravity
;
191 attr
.backing_store
= NotUseful
/*WhenMapped*/;
192 attr
.colormap
= X11DRV_PALETTE_PaletteXColormap
; /* Needed due to our visual */
195 data
->icon_window
= XCreateWindow( display
, root_window
, 0, 0,
196 GetSystemMetrics( SM_CXICON
),
197 GetSystemMetrics( SM_CYICON
),
200 CWEventMask
| CWBitGravity
| CWBackingStore
| CWColormap
, &attr
);
201 XSaveContext( display
, data
->icon_window
, winContext
, (char *)win
->hwndSelf
);
204 TRACE( "created %lx\n", data
->icon_window
);
205 SetPropA( win
->hwndSelf
, icon_window_atom
, (HANDLE
)data
->icon_window
);
206 return data
->icon_window
;
211 /***********************************************************************
212 * destroy_icon_window
214 inline static void destroy_icon_window( Display
*display
, WND
*win
)
216 struct x11drv_win_data
*data
= win
->pDriverData
;
218 if (!data
->icon_window
) return;
219 if (x11drv_thread_data()->cursor_window
== data
->icon_window
)
220 x11drv_thread_data()->cursor_window
= None
;
222 XDeleteContext( display
, data
->icon_window
, winContext
);
223 XDestroyWindow( display
, data
->icon_window
);
224 data
->icon_window
= 0;
226 RemovePropA( win
->hwndSelf
, icon_window_atom
);
230 /***********************************************************************
233 * Set the icon wm hints
235 static void set_icon_hints( Display
*display
, WND
*wndPtr
, XWMHints
*hints
)
237 X11DRV_WND_DATA
*data
= wndPtr
->pDriverData
;
238 HICON hIcon
= (HICON
)GetClassLongA( wndPtr
->hwndSelf
, GCL_HICON
);
240 if (data
->hWMIconBitmap
) DeleteObject( data
->hWMIconBitmap
);
241 if (data
->hWMIconMask
) DeleteObject( data
->hWMIconMask
);
242 data
->hWMIconBitmap
= 0;
243 data
->hWMIconMask
= 0;
245 if (!(wndPtr
->dwExStyle
& WS_EX_MANAGED
))
247 destroy_icon_window( display
, wndPtr
);
248 hints
->flags
&= ~(IconPixmapHint
| IconMaskHint
| IconWindowHint
);
252 if (!data
->icon_window
) create_icon_window( display
, wndPtr
);
253 hints
->icon_window
= data
->icon_window
;
254 hints
->flags
= (hints
->flags
& ~(IconPixmapHint
| IconMaskHint
)) | IconWindowHint
;
264 GetIconInfo(hIcon
, &ii
);
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
, ii
.hbmColor
); /* force the color bitmap to x11drv mode too */
276 SelectObject(hDC
, hbmOrig
);
279 data
->hWMIconBitmap
= ii
.hbmColor
;
280 data
->hWMIconMask
= ii
.hbmMask
;
282 hints
->icon_pixmap
= X11DRV_BITMAP_Pixmap(data
->hWMIconBitmap
);
283 hints
->icon_mask
= X11DRV_BITMAP_Pixmap(data
->hWMIconMask
);
284 destroy_icon_window( display
, wndPtr
);
285 hints
->flags
= (hints
->flags
& ~IconWindowHint
) | IconPixmapHint
| IconMaskHint
;
290 /***********************************************************************
293 * set the window size hints
295 static void set_size_hints( Display
*display
, WND
*win
)
297 XSizeHints
* size_hints
;
298 struct x11drv_win_data
*data
= win
->pDriverData
;
300 if ((size_hints
= XAllocSizeHints()))
302 size_hints
->win_gravity
= StaticGravity
;
303 size_hints
->x
= data
->whole_rect
.left
;
304 size_hints
->y
= data
->whole_rect
.top
;
305 size_hints
->flags
= PWinGravity
| PPosition
;
307 if (HAS_DLGFRAME( win
->dwStyle
, win
->dwExStyle
))
309 size_hints
->max_width
= data
->whole_rect
.right
- data
->whole_rect
.left
;
310 size_hints
->max_height
= data
->whole_rect
.bottom
- data
->whole_rect
.top
;
311 size_hints
->min_width
= size_hints
->max_width
;
312 size_hints
->min_height
= size_hints
->max_height
;
313 size_hints
->flags
|= PMinSize
| PMaxSize
;
315 XSetWMNormalHints( display
, data
->whole_window
, size_hints
);
321 /***********************************************************************
322 * X11DRV_set_wm_hints
324 * Set the window manager hints for a newly-created window
326 void X11DRV_set_wm_hints( Display
*display
, WND
*win
)
328 struct x11drv_win_data
*data
= win
->pDriverData
;
330 XClassHint
*class_hints
;
339 protocols
[i
++] = wmDeleteWindow
;
340 if (wmTakeFocus
) protocols
[i
++] = wmTakeFocus
;
341 XSetWMProtocols( display
, data
->whole_window
, protocols
, i
);
344 if ((class_hints
= XAllocClassHint()))
346 class_hints
->res_name
= "wine";
347 class_hints
->res_class
= "Wine";
348 XSetClassHint( display
, data
->whole_window
, class_hints
);
349 XFree( class_hints
);
352 /* transient for hint */
355 Window owner_win
= X11DRV_get_whole_window( win
->owner
);
356 XSetTransientForHint( display
, data
->whole_window
, owner_win
);
357 group_leader
= owner_win
;
359 else group_leader
= data
->whole_window
;
362 set_size_hints( display
, win
);
364 /* systray properties (KDE only for now) */
365 if (win
->dwExStyle
& WS_EX_TRAYWINDOW
)
368 if (kwmDockWindow
!= None
)
369 XChangeProperty( display
, data
->whole_window
, kwmDockWindow
, kwmDockWindow
,
370 32, PropModeReplace
, (char*)&val
, 1 );
371 if (_kde_net_wm_system_tray_window_for
!= None
)
372 XChangeProperty( display
, data
->whole_window
, _kde_net_wm_system_tray_window_for
,
373 XA_WINDOW
, 32, PropModeReplace
, (char*)&data
->whole_window
, 1 );
376 if (mwmHints
!= None
)
379 mwm_hints
.flags
= MWM_HINTS_FUNCTIONS
| MWM_HINTS_DECORATIONS
;
380 mwm_hints
.functions
= 0;
381 if ((win
->dwStyle
& WS_CAPTION
) == WS_CAPTION
) mwm_hints
.functions
|= MWM_FUNC_MOVE
;
382 if (win
->dwStyle
& WS_THICKFRAME
) mwm_hints
.functions
|= MWM_FUNC_MOVE
| MWM_FUNC_RESIZE
;
383 if (win
->dwStyle
& WS_MINIMIZEBOX
) mwm_hints
.functions
|= MWM_FUNC_MINIMIZE
;
384 if (win
->dwStyle
& WS_MAXIMIZEBOX
) mwm_hints
.functions
|= MWM_FUNC_MAXIMIZE
;
385 if (win
->dwStyle
& WS_SYSMENU
) mwm_hints
.functions
|= MWM_FUNC_CLOSE
;
386 mwm_hints
.decorations
= 0;
387 if ((win
->dwStyle
& WS_CAPTION
) == WS_CAPTION
) mwm_hints
.decorations
|= MWM_DECOR_TITLE
;
388 if (win
->dwExStyle
& WS_EX_DLGMODALFRAME
) mwm_hints
.decorations
|= MWM_DECOR_BORDER
;
389 else if (win
->dwStyle
& WS_THICKFRAME
) mwm_hints
.decorations
|= MWM_DECOR_BORDER
| MWM_DECOR_RESIZEH
;
390 else if ((win
->dwStyle
& (WS_DLGFRAME
|WS_BORDER
)) == WS_DLGFRAME
) mwm_hints
.decorations
|= MWM_DECOR_BORDER
;
391 else if (win
->dwStyle
& WS_BORDER
) mwm_hints
.decorations
|= MWM_DECOR_BORDER
;
392 else if (!(win
->dwStyle
& (WS_CHILD
|WS_POPUP
))) mwm_hints
.decorations
|= MWM_DECOR_BORDER
;
393 if (win
->dwStyle
& WS_SYSMENU
) mwm_hints
.decorations
|= MWM_DECOR_MENU
;
394 if (win
->dwStyle
& WS_MINIMIZEBOX
) mwm_hints
.decorations
|= MWM_DECOR_MINIMIZE
;
395 if (win
->dwStyle
& WS_MAXIMIZEBOX
) mwm_hints
.decorations
|= MWM_DECOR_MAXIMIZE
;
397 XChangeProperty( display
, data
->whole_window
, mwmHints
, mwmHints
, 32,
398 PropModeReplace
, (char*)&mwm_hints
, sizeof(mwm_hints
)/sizeof(long) );
401 wm_hints
= XAllocWMHints();
407 wm_hints
->flags
= InputHint
| StateHint
| WindowGroupHint
;
408 wm_hints
->input
= !(win
->dwStyle
& WS_DISABLED
);
410 set_icon_hints( display
, win
, wm_hints
);
412 wm_hints
->initial_state
= (win
->dwStyle
& WS_MINIMIZE
) ? IconicState
: NormalState
;
413 wm_hints
->window_group
= group_leader
;
416 XSetWMHints( display
, data
->whole_window
, wm_hints
);
423 /***********************************************************************
424 * X11DRV_set_iconic_state
426 * Set the X11 iconic state according to the window style.
428 void X11DRV_set_iconic_state( WND
*win
)
430 Display
*display
= thread_display();
431 struct x11drv_win_data
*data
= win
->pDriverData
;
433 BOOL iconic
= IsIconic( win
->hwndSelf
);
437 if (iconic
) XUnmapWindow( display
, data
->client_window
);
438 else if (is_client_window_mapped( win
)) XMapWindow( display
, data
->client_window
);
440 if (!(wm_hints
= XGetWMHints( display
, data
->whole_window
))) wm_hints
= XAllocWMHints();
441 wm_hints
->flags
|= StateHint
| IconPositionHint
;
442 wm_hints
->initial_state
= iconic
? IconicState
: NormalState
;
443 wm_hints
->icon_x
= win
->rectWindow
.left
;
444 wm_hints
->icon_y
= win
->rectWindow
.top
;
445 XSetWMHints( display
, data
->whole_window
, wm_hints
);
447 if (win
->dwStyle
& WS_VISIBLE
)
450 XIconifyWindow( display
, data
->whole_window
, DefaultScreen(display
) );
452 if (!IsRectEmpty( &win
->rectWindow
)) XMapWindow( display
, data
->whole_window
);
460 /***********************************************************************
461 * X11DRV_window_to_X_rect
463 * Convert a rect from client to X window coordinates
465 void X11DRV_window_to_X_rect( WND
*win
, RECT
*rect
)
469 if (!(win
->dwExStyle
& WS_EX_MANAGED
)) return;
470 if (IsRectEmpty( rect
)) return;
472 rc
.top
= rc
.bottom
= rc
.left
= rc
.right
= 0;
474 AdjustWindowRectEx( &rc
, win
->dwStyle
& ~(WS_HSCROLL
|WS_VSCROLL
), FALSE
, win
->dwExStyle
);
476 rect
->left
-= rc
.left
;
477 rect
->right
-= rc
.right
;
479 rect
->bottom
-= rc
.bottom
;
480 if (rect
->top
>= rect
->bottom
) rect
->bottom
= rect
->top
+ 1;
481 if (rect
->left
>= rect
->right
) rect
->right
= rect
->left
+ 1;
485 /***********************************************************************
486 * X11DRV_X_to_window_rect
488 * Opposite of X11DRV_window_to_X_rect
490 void X11DRV_X_to_window_rect( WND
*win
, RECT
*rect
)
492 if (!(win
->dwExStyle
& WS_EX_MANAGED
)) return;
493 if (IsRectEmpty( rect
)) return;
495 AdjustWindowRectEx( rect
, win
->dwStyle
& ~(WS_HSCROLL
|WS_VSCROLL
), FALSE
, win
->dwExStyle
);
497 if (rect
->top
>= rect
->bottom
) rect
->bottom
= rect
->top
+ 1;
498 if (rect
->left
>= rect
->right
) rect
->right
= rect
->left
+ 1;
502 /***********************************************************************
503 * X11DRV_sync_whole_window_position
505 * Synchronize the X whole window position with the Windows one
507 int X11DRV_sync_whole_window_position( Display
*display
, WND
*win
, int zorder
)
509 XWindowChanges changes
;
511 struct x11drv_win_data
*data
= win
->pDriverData
;
512 RECT whole_rect
= win
->rectWindow
;
514 X11DRV_window_to_X_rect( win
, &whole_rect
);
515 mask
= get_window_changes( &changes
, &data
->whole_rect
, &whole_rect
);
519 /* find window that this one must be after */
520 HWND prev
= GetWindow( win
->hwndSelf
, GW_HWNDPREV
);
521 while (prev
&& !(GetWindowLongW( prev
, GWL_STYLE
) & WS_VISIBLE
))
522 prev
= GetWindow( prev
, GW_HWNDPREV
);
523 if (!prev
) /* top child */
525 changes
.stack_mode
= Above
;
530 changes
.stack_mode
= Below
;
531 changes
.sibling
= X11DRV_get_whole_window(prev
);
532 mask
|= CWStackMode
| CWSibling
;
536 data
->whole_rect
= whole_rect
;
540 TRACE( "setting win %lx pos %ld,%ld,%ldx%ld after %lx changes=%x\n",
541 data
->whole_window
, whole_rect
.left
, whole_rect
.top
,
542 whole_rect
.right
- whole_rect
.left
, whole_rect
.bottom
- whole_rect
.top
,
543 changes
.sibling
, mask
);
545 XSync( gdi_display
, False
); /* flush graphics operations before moving the window */
546 if (is_window_top_level( win
))
548 if (mask
& (CWWidth
|CWHeight
)) set_size_hints( display
, win
);
549 XReconfigureWMWindow( display
, data
->whole_window
,
550 DefaultScreen(display
), mask
, &changes
);
552 else XConfigureWindow( display
, data
->whole_window
, mask
, &changes
);
559 /***********************************************************************
560 * X11DRV_sync_client_window_position
562 * Synchronize the X client window position with the Windows one
564 int X11DRV_sync_client_window_position( Display
*display
, WND
*win
)
566 XWindowChanges changes
;
568 struct x11drv_win_data
*data
= win
->pDriverData
;
569 RECT client_rect
= win
->rectClient
;
571 OffsetRect( &client_rect
, -data
->whole_rect
.left
, -data
->whole_rect
.top
);
573 if ((mask
= get_window_changes( &changes
, &data
->client_rect
, &client_rect
)))
575 BOOL was_mapped
= is_client_window_mapped( win
);
577 TRACE( "setting win %lx pos %ld,%ld,%ldx%ld (was %ld,%ld,%ldx%ld) after %lx changes=%x\n",
578 data
->client_window
, client_rect
.left
, client_rect
.top
,
579 client_rect
.right
- client_rect
.left
, client_rect
.bottom
- client_rect
.top
,
580 data
->client_rect
.left
, data
->client_rect
.top
,
581 data
->client_rect
.right
- data
->client_rect
.left
,
582 data
->client_rect
.bottom
- data
->client_rect
.top
,
583 changes
.sibling
, mask
);
584 data
->client_rect
= client_rect
;
586 XSync( gdi_display
, False
); /* flush graphics operations before moving the window */
587 if (was_mapped
&& !is_client_window_mapped( win
))
588 XUnmapWindow( display
, data
->client_window
);
589 XConfigureWindow( display
, data
->client_window
, mask
, &changes
);
590 if (!was_mapped
&& is_client_window_mapped( win
))
591 XMapWindow( display
, data
->client_window
);
598 /***********************************************************************
599 * X11DRV_register_window
601 * Associate an X window to a HWND.
603 void X11DRV_register_window( Display
*display
, HWND hwnd
, struct x11drv_win_data
*data
)
606 XSaveContext( display
, data
->whole_window
, winContext
, (char *)hwnd
);
607 XSaveContext( display
, data
->client_window
, winContext
, (char *)hwnd
);
612 /**********************************************************************
615 static void create_desktop( Display
*display
, WND
*wndPtr
, CREATESTRUCTA
*cs
)
617 X11DRV_WND_DATA
*data
= wndPtr
->pDriverData
;
620 winContext
= XUniqueContext();
621 wmProtocols
= XInternAtom( display
, "WM_PROTOCOLS", False
);
622 wmDeleteWindow
= XInternAtom( display
, "WM_DELETE_WINDOW", False
);
623 if (use_take_focus
) wmTakeFocus
= XInternAtom( display
, "WM_TAKE_FOCUS", False
);
624 dndProtocol
= XInternAtom( display
, "DndProtocol" , False
);
625 dndSelection
= XInternAtom( display
, "DndSelection" , False
);
626 wmChangeState
= XInternAtom( display
, "WM_CHANGE_STATE", False
);
627 mwmHints
= XInternAtom( display
, _XA_MWM_HINTS
, False
);
628 kwmDockWindow
= XInternAtom( display
, "KWM_DOCKWINDOW", False
);
629 _kde_net_wm_system_tray_window_for
= XInternAtom( display
, "_KDE_NET_WM_SYSTEM_TRAY_WINDOW_FOR", False
);
632 whole_window_atom
= MAKEINTATOMA( GlobalAddAtomA( "__wine_x11_whole_window" ));
633 client_window_atom
= MAKEINTATOMA( GlobalAddAtomA( "__wine_x11_client_window" ));
634 icon_window_atom
= MAKEINTATOMA( GlobalAddAtomA( "__wine_x11_icon_window" ));
636 data
->whole_window
= data
->client_window
= root_window
;
637 data
->whole_rect
= data
->client_rect
= wndPtr
->rectWindow
;
639 SetPropA( wndPtr
->hwndSelf
, whole_window_atom
, (HANDLE
)root_window
);
640 SetPropA( wndPtr
->hwndSelf
, client_window_atom
, (HANDLE
)root_window
);
641 SetPropA( wndPtr
->hwndSelf
, "__wine_x11_visual_id", (HANDLE
)XVisualIDFromVisual(visual
) );
643 SendMessageW( wndPtr
->hwndSelf
, WM_NCCREATE
, 0, (LPARAM
)cs
);
644 if (root_window
!= DefaultRootWindow(display
)) X11DRV_create_desktop_thread();
648 /**********************************************************************
649 * create_whole_window
651 * Create the whole X window for a given window
653 static Window
create_whole_window( Display
*display
, WND
*win
)
655 struct x11drv_win_data
*data
= win
->pDriverData
;
657 XSetWindowAttributes attr
;
660 BOOL is_top_level
= is_window_top_level( win
);
662 rect
= win
->rectWindow
;
663 X11DRV_window_to_X_rect( win
, &rect
);
665 if (!(cx
= rect
.right
- rect
.left
)) cx
= 1;
666 if (!(cy
= rect
.bottom
- rect
.top
)) cy
= 1;
668 parent
= X11DRV_get_client_window( win
->parent
);
672 mask
= get_window_attributes( display
, win
, &attr
);
674 /* set the attributes that don't change over the lifetime of the window */
675 attr
.bit_gravity
= ForgetGravity
;
676 attr
.win_gravity
= NorthWestGravity
;
677 attr
.backing_store
= NotUseful
/*WhenMapped*/;
678 mask
|= CWBitGravity
| CWWinGravity
| CWBackingStore
;
680 data
->whole_rect
= rect
;
681 data
->whole_window
= XCreateWindow( display
, parent
, rect
.left
, rect
.top
, cx
, cy
,
682 0, screen_depth
, InputOutput
, visual
,
685 if (!data
->whole_window
)
693 XIM xim
= x11drv_thread_data()->xim
;
694 if (xim
) data
->xic
= XCreateIC( xim
,
695 XNInputStyle
, XIMPreeditNothing
| XIMStatusNothing
,
696 XNClientWindow
, data
->whole_window
,
697 XNFocusWindow
, data
->whole_window
,
701 /* non-maximized child must be at bottom of Z order */
702 if ((win
->dwStyle
& (WS_CHILD
|WS_MAXIMIZE
)) == WS_CHILD
)
704 XWindowChanges changes
;
705 changes
.stack_mode
= Below
;
706 XConfigureWindow( display
, data
->whole_window
, CWStackMode
, &changes
);
711 if (is_top_level
) X11DRV_set_wm_hints( display
, win
);
713 return data
->whole_window
;
717 /**********************************************************************
718 * create_client_window
720 * Create the client window for a given window
722 static Window
create_client_window( Display
*display
, WND
*win
)
724 struct x11drv_win_data
*data
= win
->pDriverData
;
725 RECT rect
= data
->whole_rect
;
726 XSetWindowAttributes attr
;
728 OffsetRect( &rect
, -data
->whole_rect
.left
, -data
->whole_rect
.top
);
729 data
->client_rect
= rect
;
731 attr
.event_mask
= (ExposureMask
| PointerMotionMask
|
732 ButtonPressMask
| ButtonReleaseMask
| EnterWindowMask
);
733 attr
.bit_gravity
= (win
->clsStyle
& (CS_VREDRAW
| CS_HREDRAW
)) ?
734 ForgetGravity
: NorthWestGravity
;
735 attr
.backing_store
= NotUseful
/*WhenMapped*/;
738 data
->client_window
= XCreateWindow( display
, data
->whole_window
, 0, 0,
739 max( rect
.right
- rect
.left
, 1 ),
740 max( rect
.bottom
- rect
.top
, 1 ),
743 CWEventMask
| CWBitGravity
| CWBackingStore
, &attr
);
744 if (data
->client_window
&& is_client_window_mapped( win
))
745 XMapWindow( display
, data
->client_window
);
747 return data
->client_window
;
751 /*****************************************************************
752 * SetWindowText (X11DRV.@)
754 BOOL
X11DRV_SetWindowText( HWND hwnd
, LPCWSTR text
)
756 Display
*display
= thread_display();
760 static UINT text_cp
= (UINT
)-1;
763 if ((win
= X11DRV_get_whole_window( hwnd
)))
765 if (text_cp
== (UINT
)-1)
770 if(!RegOpenKeyA(HKEY_LOCAL_MACHINE
, "Software\\Wine\\Wine\\Config\\x11drv", &hkey
))
773 DWORD type
, count
= sizeof(buffer
);
774 if(!RegQueryValueExA(hkey
, "TextCP", 0, &type
, buffer
, &count
))
775 text_cp
= atoi(buffer
);
778 TRACE("text_cp = %u\n", text_cp
);
781 /* allocate new buffer for window text */
782 count
= WideCharToMultiByte(text_cp
, 0, text
, -1, NULL
, 0, NULL
, NULL
);
783 if (!(buffer
= HeapAlloc( GetProcessHeap(), 0, count
)))
785 ERR("Not enough memory for window text\n");
788 WideCharToMultiByte(text_cp
, 0, text
, -1, buffer
, count
, NULL
, NULL
);
790 count
= WideCharToMultiByte(CP_UTF8
, 0, text
, strlenW(text
), NULL
, 0, NULL
, NULL
);
791 if (!(utf8_buffer
= HeapAlloc( GetProcessHeap(), 0, count
)))
793 ERR("Not enough memory for window text in UTF-8\n");
796 WideCharToMultiByte(CP_UTF8
, 0, text
, strlenW(text
), utf8_buffer
, count
, NULL
, NULL
);
799 XStoreName( display
, win
, buffer
);
800 XSetIconName( display
, win
, buffer
);
802 Implements a NET_WM UTF-8 title. It should be without a trailing \0,
803 according to the standard
804 ( http://www.pps.jussieu.fr/~jch/software/UTF8_STRING/UTF8_STRING.text ).
806 XChangeProperty( display
, win
,
807 XInternAtom(display
, "_NET_WM_NAME", False
),
808 XInternAtom(display
, "UTF8_STRING", False
),
809 8, PropModeReplace
, (unsigned char *) utf8_buffer
,
813 HeapFree( GetProcessHeap(), 0, utf8_buffer
);
814 HeapFree( GetProcessHeap(), 0, buffer
);
820 /***********************************************************************
821 * DestroyWindow (X11DRV.@)
823 BOOL
X11DRV_DestroyWindow( HWND hwnd
)
825 struct x11drv_thread_data
*thread_data
= x11drv_thread_data();
826 Display
*display
= thread_data
->display
;
827 WND
*wndPtr
= WIN_GetPtr( hwnd
);
828 X11DRV_WND_DATA
*data
= wndPtr
->pDriverData
;
830 if (!data
) goto done
;
832 if (data
->whole_window
)
834 TRACE( "win %p xwin %lx/%lx\n", hwnd
, data
->whole_window
, data
->client_window
);
835 if (thread_data
->cursor_window
== data
->whole_window
) thread_data
->cursor_window
= None
;
836 if (thread_data
->last_focus
== hwnd
) thread_data
->last_focus
= 0;
838 XSync( gdi_display
, False
); /* flush any reference to this drawable in GDI queue */
839 XDeleteContext( display
, data
->whole_window
, winContext
);
840 XDeleteContext( display
, data
->client_window
, winContext
);
841 XDestroyWindow( display
, data
->whole_window
); /* this destroys client too */
844 XUnsetICFocus( data
->xic
);
845 XDestroyIC( data
->xic
);
847 destroy_icon_window( display
, wndPtr
);
851 if (data
->hWMIconBitmap
) DeleteObject( data
->hWMIconBitmap
);
852 if (data
->hWMIconMask
) DeleteObject( data
->hWMIconMask
);
853 HeapFree( GetProcessHeap(), 0, data
);
854 wndPtr
->pDriverData
= NULL
;
856 WIN_ReleasePtr( wndPtr
);
861 /**********************************************************************
862 * CreateWindow (X11DRV.@)
864 BOOL
X11DRV_CreateWindow( HWND hwnd
, CREATESTRUCTA
*cs
, BOOL unicode
)
867 Display
*display
= thread_display();
869 struct x11drv_win_data
*data
;
876 ERR( "invalid window width %d\n", cs
->cx
);
881 ERR( "invalid window height %d\n", cs
->cx
);
885 if (!(data
= HeapAlloc(GetProcessHeap(), 0, sizeof(*data
)))) return FALSE
;
886 data
->whole_window
= 0;
887 data
->client_window
= 0;
888 data
->icon_window
= 0;
890 data
->hWMIconBitmap
= 0;
891 data
->hWMIconMask
= 0;
893 wndPtr
= WIN_GetPtr( hwnd
);
894 wndPtr
->pDriverData
= data
;
896 /* initialize the dimensions before sending WM_GETMINMAXINFO */
897 SetRect( &rect
, cs
->x
, cs
->y
, cs
->x
+ cs
->cx
, cs
->y
+ cs
->cy
);
898 WIN_SetRectangles( hwnd
, &rect
, &rect
);
902 create_desktop( display
, wndPtr
, cs
);
903 WIN_ReleasePtr( wndPtr
);
907 if (!create_whole_window( display
, wndPtr
)) goto failed
;
908 if (!create_client_window( display
, wndPtr
)) goto failed
;
909 TSXSync( display
, False
);
911 SetPropA( hwnd
, whole_window_atom
, (HANDLE
)data
->whole_window
);
912 SetPropA( hwnd
, client_window_atom
, (HANDLE
)data
->client_window
);
914 /* Call the WH_CBT hook */
916 hwndLinkAfter
= ((cs
->style
& (WS_CHILD
|WS_MAXIMIZE
)) == WS_CHILD
) ? HWND_BOTTOM
: HWND_TOP
;
919 cbtc
.hwndInsertAfter
= hwndLinkAfter
;
920 if (HOOK_CallHooks( WH_CBT
, HCBT_CREATEWND
, (WPARAM
)hwnd
, (LPARAM
)&cbtc
, unicode
))
922 TRACE("CBT-hook returned !0\n");
926 /* Send the WM_GETMINMAXINFO message and fix the size if needed */
927 if ((cs
->style
& WS_THICKFRAME
) || !(cs
->style
& (WS_POPUP
| WS_CHILD
)))
929 POINT maxSize
, maxPos
, minTrack
, maxTrack
;
931 WIN_ReleasePtr( wndPtr
);
932 WINPOS_GetMinMaxInfo( hwnd
, &maxSize
, &maxPos
, &minTrack
, &maxTrack
);
933 if (maxSize
.x
< cs
->cx
) cs
->cx
= maxSize
.x
;
934 if (maxSize
.y
< cs
->cy
) cs
->cy
= maxSize
.y
;
935 if (cs
->cx
< minTrack
.x
) cs
->cx
= minTrack
.x
;
936 if (cs
->cy
< minTrack
.y
) cs
->cy
= minTrack
.y
;
937 if (cs
->cx
< 0) cs
->cx
= 0;
938 if (cs
->cy
< 0) cs
->cy
= 0;
940 if (!(wndPtr
= WIN_GetPtr( hwnd
))) return FALSE
;
941 SetRect( &rect
, cs
->x
, cs
->y
, cs
->x
+ cs
->cx
, cs
->y
+ cs
->cy
);
942 WIN_SetRectangles( hwnd
, &rect
, &rect
);
943 X11DRV_sync_whole_window_position( display
, wndPtr
, 0 );
945 WIN_ReleasePtr( wndPtr
);
947 /* send WM_NCCREATE */
948 TRACE( "hwnd %p cs %d,%d %dx%d\n", hwnd
, cs
->x
, cs
->y
, cs
->cx
, cs
->cy
);
950 ret
= SendMessageW( hwnd
, WM_NCCREATE
, 0, (LPARAM
)cs
);
952 ret
= SendMessageA( hwnd
, WM_NCCREATE
, 0, (LPARAM
)cs
);
955 WARN("aborted by WM_xxCREATE!\n");
959 if (!(wndPtr
= WIN_GetPtr(hwnd
))) return FALSE
;
961 X11DRV_sync_window_style( display
, wndPtr
);
963 /* send WM_NCCALCSIZE */
964 rect
= wndPtr
->rectWindow
;
965 WIN_ReleasePtr( wndPtr
);
966 SendMessageW( hwnd
, WM_NCCALCSIZE
, FALSE
, (LPARAM
)&rect
);
968 if (!(wndPtr
= WIN_GetPtr(hwnd
))) return FALSE
;
969 if (rect
.left
> rect
.right
|| rect
.top
> rect
.bottom
) rect
= wndPtr
->rectWindow
;
970 WIN_SetRectangles( hwnd
, &wndPtr
->rectWindow
, &rect
);
971 X11DRV_sync_client_window_position( display
, wndPtr
);
972 X11DRV_register_window( display
, hwnd
, data
);
974 TRACE( "win %p window %ld,%ld,%ld,%ld client %ld,%ld,%ld,%ld whole %ld,%ld,%ld,%ld X client %ld,%ld,%ld,%ld xwin %x/%x\n",
975 hwnd
, wndPtr
->rectWindow
.left
, wndPtr
->rectWindow
.top
,
976 wndPtr
->rectWindow
.right
, wndPtr
->rectWindow
.bottom
,
977 wndPtr
->rectClient
.left
, wndPtr
->rectClient
.top
,
978 wndPtr
->rectClient
.right
, wndPtr
->rectClient
.bottom
,
979 data
->whole_rect
.left
, data
->whole_rect
.top
,
980 data
->whole_rect
.right
, data
->whole_rect
.bottom
,
981 data
->client_rect
.left
, data
->client_rect
.top
,
982 data
->client_rect
.right
, data
->client_rect
.bottom
,
983 (unsigned int)data
->whole_window
, (unsigned int)data
->client_window
);
985 if ((wndPtr
->dwStyle
& (WS_CHILD
|WS_MAXIMIZE
)) == WS_CHILD
)
986 WIN_LinkWindow( hwnd
, wndPtr
->parent
, HWND_BOTTOM
);
988 WIN_LinkWindow( hwnd
, wndPtr
->parent
, HWND_TOP
);
990 WIN_ReleasePtr( wndPtr
);
993 ret
= (SendMessageW( hwnd
, WM_CREATE
, 0, (LPARAM
)cs
) != -1);
995 ret
= (SendMessageA( hwnd
, WM_CREATE
, 0, (LPARAM
)cs
) != -1);
999 WIN_UnlinkWindow( hwnd
);
1003 /* Send the size messages */
1005 if (!(wndPtr
= WIN_FindWndPtr(hwnd
))) return FALSE
;
1006 if (!(wndPtr
->flags
& WIN_NEED_SIZE
))
1008 /* send it anyway */
1009 if (((wndPtr
->rectClient
.right
-wndPtr
->rectClient
.left
) <0)
1010 ||((wndPtr
->rectClient
.bottom
-wndPtr
->rectClient
.top
)<0))
1011 WARN("sending bogus WM_SIZE message 0x%08lx\n",
1012 MAKELONG(wndPtr
->rectClient
.right
-wndPtr
->rectClient
.left
,
1013 wndPtr
->rectClient
.bottom
-wndPtr
->rectClient
.top
));
1014 SendMessageW( hwnd
, WM_SIZE
, SIZE_RESTORED
,
1015 MAKELONG(wndPtr
->rectClient
.right
-wndPtr
->rectClient
.left
,
1016 wndPtr
->rectClient
.bottom
-wndPtr
->rectClient
.top
));
1017 SendMessageW( hwnd
, WM_MOVE
, 0,
1018 MAKELONG( wndPtr
->rectClient
.left
, wndPtr
->rectClient
.top
) );
1021 /* Show the window, maximizing or minimizing if needed */
1023 if (wndPtr
->dwStyle
& (WS_MINIMIZE
| WS_MAXIMIZE
))
1025 extern UINT
WINPOS_MinMaximize( HWND hwnd
, UINT cmd
, LPRECT rect
); /*FIXME*/
1028 UINT swFlag
= (wndPtr
->dwStyle
& WS_MINIMIZE
) ? SW_MINIMIZE
: SW_MAXIMIZE
;
1029 WIN_SetStyle( hwnd
, wndPtr
->dwStyle
& ~(WS_MAXIMIZE
| WS_MINIMIZE
) );
1030 WINPOS_MinMaximize( hwnd
, swFlag
, &newPos
);
1031 swFlag
= ((wndPtr
->dwStyle
& WS_CHILD
) || GetActiveWindow())
1032 ? SWP_NOACTIVATE
| SWP_NOZORDER
| SWP_FRAMECHANGED
1033 : SWP_NOZORDER
| SWP_FRAMECHANGED
;
1034 SetWindowPos( hwnd
, 0, newPos
.left
, newPos
.top
,
1035 newPos
.right
, newPos
.bottom
, swFlag
);
1038 /* if the window was made visible set create struct flag so that
1039 * we do a proper ShowWindow later on */
1040 if (wndPtr
->dwStyle
& WS_VISIBLE
) cs
->style
|= WS_VISIBLE
;
1042 WIN_ReleaseWndPtr( wndPtr
);
1047 X11DRV_DestroyWindow( hwnd
);
1048 if (wndPtr
) WIN_ReleasePtr( wndPtr
);
1053 /***********************************************************************
1054 * X11DRV_get_client_window
1056 * Return the X window associated with the client area of a window
1058 Window
X11DRV_get_client_window( HWND hwnd
)
1061 WND
*win
= WIN_GetPtr( hwnd
);
1063 if (win
== WND_OTHER_PROCESS
)
1064 return (Window
)GetPropA( hwnd
, client_window_atom
);
1068 struct x11drv_win_data
*data
= win
->pDriverData
;
1069 ret
= data
->client_window
;
1070 WIN_ReleasePtr( win
);
1076 /***********************************************************************
1077 * X11DRV_get_whole_window
1079 * Return the X window associated with the full area of a window
1081 Window
X11DRV_get_whole_window( HWND hwnd
)
1084 WND
*win
= WIN_GetPtr( hwnd
);
1086 if (win
== WND_OTHER_PROCESS
)
1087 return (Window
)GetPropA( hwnd
, whole_window_atom
);
1091 struct x11drv_win_data
*data
= win
->pDriverData
;
1092 ret
= data
->whole_window
;
1093 WIN_ReleasePtr( win
);
1099 /***********************************************************************
1102 * Return the X input context associated with a window
1104 XIC
X11DRV_get_ic( HWND hwnd
)
1107 WND
*win
= WIN_GetPtr( hwnd
);
1109 if (win
&& win
!= WND_OTHER_PROCESS
)
1111 struct x11drv_win_data
*data
= win
->pDriverData
;
1113 WIN_ReleasePtr( win
);
1119 /*****************************************************************
1120 * SetParent (X11DRV.@)
1122 HWND
X11DRV_SetParent( HWND hwnd
, HWND parent
)
1124 Display
*display
= thread_display();
1128 /* Windows hides the window first, then shows it again
1129 * including the WM_SHOWWINDOW messages and all */
1130 BOOL was_visible
= ShowWindow( hwnd
, SW_HIDE
);
1132 if (!IsWindow( parent
)) return 0;
1133 if (!(wndPtr
= WIN_GetPtr(hwnd
)) || wndPtr
== WND_OTHER_PROCESS
) return 0;
1135 retvalue
= wndPtr
->parent
; /* old parent */
1136 if (parent
!= retvalue
)
1138 struct x11drv_win_data
*data
= wndPtr
->pDriverData
;
1140 WIN_LinkWindow( hwnd
, parent
, HWND_TOP
);
1142 if (parent
!= GetDesktopWindow()) /* a child window */
1144 if (!(wndPtr
->dwStyle
& WS_CHILD
))
1146 HMENU menu
= (HMENU
)SetWindowLongW( hwnd
, GWL_ID
, 0 );
1147 if (menu
) DestroyMenu( menu
);
1151 if (is_window_top_level( wndPtr
)) X11DRV_set_wm_hints( display
, wndPtr
);
1153 X11DRV_sync_window_style( display
, wndPtr
);
1154 XReparentWindow( display
, data
->whole_window
, X11DRV_get_client_window(parent
),
1155 data
->whole_rect
.left
, data
->whole_rect
.top
);
1156 wine_tsx11_unlock();
1158 WIN_ReleasePtr( wndPtr
);
1160 /* SetParent additionally needs to make hwnd the topmost window
1161 in the x-order and send the expected WM_WINDOWPOSCHANGING and
1162 WM_WINDOWPOSCHANGED notification messages.
1164 SetWindowPos( hwnd
, HWND_TOPMOST
, 0, 0, 0, 0,
1165 SWP_NOACTIVATE
| SWP_NOMOVE
| SWP_NOSIZE
| (was_visible
? SWP_SHOWWINDOW
: 0) );
1166 /* FIXME: a WM_MOVE is also generated (in the DefWindowProc handler
1167 * for WM_WINDOWPOSCHANGED) in Windows, should probably remove SWP_NOMOVE */
1173 /*****************************************************************
1174 * SetFocus (X11DRV.@)
1177 * Explicit colormap management seems to work only with OLVWM.
1179 void X11DRV_SetFocus( HWND hwnd
)
1181 Display
*display
= thread_display();
1182 XWindowAttributes win_attr
;
1185 /* Only mess with the X focus if there's */
1186 /* no desktop window and if the window is not managed by the WM. */
1187 if (root_window
!= DefaultRootWindow(display
)) return;
1189 if (!hwnd
) /* If setting the focus to 0, uninstall the colormap */
1191 if (X11DRV_PALETTE_PaletteFlags
& X11DRV_PALETTE_PRIVATE
)
1192 TSXUninstallColormap( display
, X11DRV_PALETTE_PaletteXColormap
);
1196 hwnd
= GetAncestor( hwnd
, GA_ROOT
);
1197 if (GetWindowLongW( hwnd
, GWL_EXSTYLE
) & WS_EX_MANAGED
) return;
1198 if (!(win
= X11DRV_get_whole_window( hwnd
))) return;
1200 /* Set X focus and install colormap */
1202 if (XGetWindowAttributes( display
, win
, &win_attr
) &&
1203 (win_attr
.map_state
== IsViewable
))
1205 /* If window is not viewable, don't change anything */
1207 /* we must not use CurrentTime (ICCCM), so try to use last message time instead */
1208 /* FIXME: this is not entirely correct */
1209 XSetInputFocus( display
, win
, RevertToParent
,
1210 /*CurrentTime*/ GetMessageTime() + X11DRV_server_startticks
);
1211 if (X11DRV_PALETTE_PaletteFlags
& X11DRV_PALETTE_PRIVATE
)
1212 XInstallColormap( display
, X11DRV_PALETTE_PaletteXColormap
);
1214 wine_tsx11_unlock();
1218 /**********************************************************************
1219 * SetWindowIcon (X11DRV.@)
1221 * hIcon or hIconSm has changed (or is being initialised for the
1222 * first time). Complete the X11 driver-specific initialisation
1223 * and set the window hints.
1225 * This is not entirely correct, may need to create
1226 * an icon window and set the pixmap as a background
1228 HICON
X11DRV_SetWindowIcon( HWND hwnd
, HICON icon
, BOOL small
)
1231 Display
*display
= thread_display();
1232 HICON old
= (HICON
)SetClassLongW(hwnd
, small
? GCL_HICONSM
: GCL_HICON
, (LONG
)icon
);
1234 SetWindowPos( hwnd
, 0, 0, 0, 0, 0, SWP_FRAMECHANGED
| SWP_NOSIZE
|
1235 SWP_NOMOVE
| SWP_NOACTIVATE
| SWP_NOZORDER
);
1237 if (!(wndPtr
= WIN_GetPtr( hwnd
)) || wndPtr
== WND_OTHER_PROCESS
) return old
;
1239 if (wndPtr
->dwExStyle
& WS_EX_MANAGED
)
1241 Window win
= get_whole_window(wndPtr
);
1245 if (!(wm_hints
= XGetWMHints( display
, win
))) wm_hints
= XAllocWMHints();
1246 wine_tsx11_unlock();
1249 set_icon_hints( display
, wndPtr
, wm_hints
);
1251 XSetWMHints( display
, win
, wm_hints
);
1253 wine_tsx11_unlock();
1256 WIN_ReleasePtr( wndPtr
);