2 * X11DRV desktop window handling
4 * Copyright 2001 Alexandre Julliard
5 * Copyright 2020 Zhiyi Zhang for CodeWeavers
7 * This library is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU Lesser General Public
9 * License as published by the Free Software Foundation; either
10 * version 2.1 of the License, or (at your option) any later version.
12 * This library is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Lesser General Public License for more details.
17 * You should have received a copy of the GNU Lesser General Public
18 * License along with this library; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
27 #include <X11/cursorfont.h>
30 #define NONAMELESSSTRUCT
31 #define NONAMELESSUNION
35 /* avoid conflict with field names in included win32 headers */
37 #include "wine/debug.h"
39 WINE_DEFAULT_DEBUG_CHANNEL(x11drv
);
41 static RECT host_primary_rect
;
43 #define _NET_WM_STATE_REMOVE 0
44 #define _NET_WM_STATE_ADD 1
46 /* Return TRUE if Wine is currently in virtual desktop mode */
47 BOOL
is_virtual_desktop(void)
49 return root_window
!= DefaultRootWindow( gdi_display
);
52 /***********************************************************************
55 * Setup the desktop when not using the root window.
57 void X11DRV_init_desktop( Window win
, unsigned int width
, unsigned int height
)
59 host_primary_rect
= get_host_primary_monitor_rect();
61 managed_mode
= FALSE
; /* no managed windows in desktop mode */
64 /***********************************************************************
65 * X11DRV_CreateDesktop
67 * Create the X11 desktop window for the desktop mode.
69 BOOL
X11DRV_CreateDesktop( const WCHAR
*name
, UINT width
, UINT height
)
71 XSetWindowAttributes win_attr
;
73 Display
*display
= thread_init_display();
75 TRACE( "%s %ux%u\n", debugstr_w(name
), width
, height
);
78 win_attr
.event_mask
= ExposureMask
| KeyPressMask
| KeyReleaseMask
| EnterWindowMask
|
79 PointerMotionMask
| ButtonPressMask
| ButtonReleaseMask
| FocusChangeMask
;
80 win_attr
.cursor
= XCreateFontCursor( display
, XC_top_left_arrow
);
82 if (default_visual
.visual
!= DefaultVisual( display
, DefaultScreen(display
) ))
83 win_attr
.colormap
= XCreateColormap( display
, DefaultRootWindow(display
),
84 default_visual
.visual
, AllocNone
);
86 win_attr
.colormap
= None
;
88 win
= XCreateWindow( display
, DefaultRootWindow(display
),
89 0, 0, width
, height
, 0, default_visual
.depth
, InputOutput
,
90 default_visual
.visual
, CWEventMask
| CWCursor
| CWColormap
, &win_attr
);
91 if (!win
) return FALSE
;
94 X11DRV_init_desktop( win
, width
, height
);
98 BOOL
is_desktop_fullscreen(void)
100 RECT primary_rect
= NtUserGetPrimaryMonitorRect();
101 return (primary_rect
.right
- primary_rect
.left
== host_primary_rect
.right
- host_primary_rect
.left
&&
102 primary_rect
.bottom
- primary_rect
.top
== host_primary_rect
.bottom
- host_primary_rect
.top
);
105 static void update_desktop_fullscreen( unsigned int width
, unsigned int height
)
107 Display
*display
= thread_display();
110 if (!display
|| !is_virtual_desktop()) return;
112 xev
.xclient
.type
= ClientMessage
;
113 xev
.xclient
.window
= root_window
;
114 xev
.xclient
.message_type
= x11drv_atom(_NET_WM_STATE
);
115 xev
.xclient
.serial
= 0;
116 xev
.xclient
.display
= display
;
117 xev
.xclient
.send_event
= True
;
118 xev
.xclient
.format
= 32;
119 if (width
== host_primary_rect
.right
- host_primary_rect
.left
&& height
== host_primary_rect
.bottom
- host_primary_rect
.top
)
120 xev
.xclient
.data
.l
[0] = _NET_WM_STATE_ADD
;
122 xev
.xclient
.data
.l
[0] = _NET_WM_STATE_REMOVE
;
123 xev
.xclient
.data
.l
[1] = x11drv_atom(_NET_WM_STATE_FULLSCREEN
);
124 xev
.xclient
.data
.l
[2] = 0;
125 xev
.xclient
.data
.l
[3] = 1;
127 TRACE("action=%li\n", xev
.xclient
.data
.l
[0]);
129 XSendEvent( display
, DefaultRootWindow(display
), False
,
130 SubstructureRedirectMask
| SubstructureNotifyMask
, &xev
);
132 xev
.xclient
.data
.l
[1] = x11drv_atom(_NET_WM_STATE_MAXIMIZED_VERT
);
133 xev
.xclient
.data
.l
[2] = x11drv_atom(_NET_WM_STATE_MAXIMIZED_HORZ
);
134 XSendEvent( display
, DefaultRootWindow(display
), False
,
135 SubstructureRedirectMask
| SubstructureNotifyMask
, &xev
);
138 /***********************************************************************
139 * X11DRV_resize_desktop
141 void X11DRV_resize_desktop(void)
143 static RECT old_virtual_rect
;
145 RECT primary_rect
, virtual_rect
;
146 HWND hwnd
= NtUserGetDesktopWindow();
149 virtual_rect
= NtUserGetVirtualScreenRect();
150 primary_rect
= NtUserGetPrimaryMonitorRect();
151 width
= primary_rect
.right
;
152 height
= primary_rect
.bottom
;
154 TRACE( "desktop %p change to (%dx%d)\n", hwnd
, width
, height
);
155 update_desktop_fullscreen( width
, height
);
156 NtUserSetWindowPos( hwnd
, 0, virtual_rect
.left
, virtual_rect
.top
,
157 virtual_rect
.right
- virtual_rect
.left
, virtual_rect
.bottom
- virtual_rect
.top
,
158 SWP_NOZORDER
| SWP_NOACTIVATE
| SWP_DEFERERASE
);
160 if (old_virtual_rect
.left
!= virtual_rect
.left
|| old_virtual_rect
.top
!= virtual_rect
.top
)
161 send_message_timeout( HWND_BROADCAST
, WM_X11DRV_DESKTOP_RESIZED
, old_virtual_rect
.left
,
162 old_virtual_rect
.top
, SMTO_ABORTIFHUNG
, 2000, FALSE
);
164 old_virtual_rect
= virtual_rect
;