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>
32 /* avoid conflict with field names in included win32 headers */
34 #include "wine/debug.h"
36 WINE_DEFAULT_DEBUG_CHANNEL(x11drv
);
38 static RECT host_primary_rect
;
40 #define _NET_WM_STATE_REMOVE 0
41 #define _NET_WM_STATE_ADD 1
43 /* Return TRUE if Wine is currently in virtual desktop mode */
44 BOOL
is_virtual_desktop(void)
46 return root_window
!= DefaultRootWindow( gdi_display
);
49 /***********************************************************************
52 * Setup the desktop when not using the root window.
54 void X11DRV_init_desktop( Window win
, unsigned int width
, unsigned int height
)
56 host_primary_rect
= get_host_primary_monitor_rect();
58 managed_mode
= FALSE
; /* no managed windows in desktop mode */
61 /***********************************************************************
62 * X11DRV_CreateDesktop
64 * Create the X11 desktop window for the desktop mode.
66 BOOL
X11DRV_CreateDesktop( const WCHAR
*name
, UINT width
, UINT height
)
68 XSetWindowAttributes win_attr
;
70 Display
*display
= thread_init_display();
72 TRACE( "%s %ux%u\n", debugstr_w(name
), width
, height
);
75 win_attr
.event_mask
= ExposureMask
| KeyPressMask
| KeyReleaseMask
| EnterWindowMask
|
76 PointerMotionMask
| ButtonPressMask
| ButtonReleaseMask
| FocusChangeMask
;
77 win_attr
.cursor
= XCreateFontCursor( display
, XC_top_left_arrow
);
79 if (default_visual
.visual
!= DefaultVisual( display
, DefaultScreen(display
) ))
80 win_attr
.colormap
= XCreateColormap( display
, DefaultRootWindow(display
),
81 default_visual
.visual
, AllocNone
);
83 win_attr
.colormap
= None
;
85 win
= XCreateWindow( display
, DefaultRootWindow(display
),
86 0, 0, width
, height
, 0, default_visual
.depth
, InputOutput
,
87 default_visual
.visual
, CWEventMask
| CWCursor
| CWColormap
, &win_attr
);
88 if (!win
) return FALSE
;
91 X11DRV_init_desktop( win
, width
, height
);
95 BOOL
is_desktop_fullscreen(void)
97 RECT primary_rect
= NtUserGetPrimaryMonitorRect();
98 return (primary_rect
.right
- primary_rect
.left
== host_primary_rect
.right
- host_primary_rect
.left
&&
99 primary_rect
.bottom
- primary_rect
.top
== host_primary_rect
.bottom
- host_primary_rect
.top
);
102 static void update_desktop_fullscreen( unsigned int width
, unsigned int height
)
104 Display
*display
= thread_display();
107 if (!display
|| !is_virtual_desktop()) return;
109 xev
.xclient
.type
= ClientMessage
;
110 xev
.xclient
.window
= root_window
;
111 xev
.xclient
.message_type
= x11drv_atom(_NET_WM_STATE
);
112 xev
.xclient
.serial
= 0;
113 xev
.xclient
.display
= display
;
114 xev
.xclient
.send_event
= True
;
115 xev
.xclient
.format
= 32;
116 if (width
== host_primary_rect
.right
- host_primary_rect
.left
&& height
== host_primary_rect
.bottom
- host_primary_rect
.top
)
117 xev
.xclient
.data
.l
[0] = _NET_WM_STATE_ADD
;
119 xev
.xclient
.data
.l
[0] = _NET_WM_STATE_REMOVE
;
120 xev
.xclient
.data
.l
[1] = x11drv_atom(_NET_WM_STATE_FULLSCREEN
);
121 xev
.xclient
.data
.l
[2] = 0;
122 xev
.xclient
.data
.l
[3] = 1;
124 TRACE("action=%li\n", xev
.xclient
.data
.l
[0]);
126 XSendEvent( display
, DefaultRootWindow(display
), False
,
127 SubstructureRedirectMask
| SubstructureNotifyMask
, &xev
);
129 xev
.xclient
.data
.l
[1] = x11drv_atom(_NET_WM_STATE_MAXIMIZED_VERT
);
130 xev
.xclient
.data
.l
[2] = x11drv_atom(_NET_WM_STATE_MAXIMIZED_HORZ
);
131 XSendEvent( display
, DefaultRootWindow(display
), False
,
132 SubstructureRedirectMask
| SubstructureNotifyMask
, &xev
);
135 /***********************************************************************
136 * X11DRV_resize_desktop
138 void X11DRV_resize_desktop(void)
140 static RECT old_virtual_rect
;
142 RECT primary_rect
, virtual_rect
;
143 HWND hwnd
= NtUserGetDesktopWindow();
146 virtual_rect
= NtUserGetVirtualScreenRect();
147 primary_rect
= NtUserGetPrimaryMonitorRect();
148 width
= primary_rect
.right
;
149 height
= primary_rect
.bottom
;
151 TRACE( "desktop %p change to (%dx%d)\n", hwnd
, width
, height
);
152 update_desktop_fullscreen( width
, height
);
153 NtUserSetWindowPos( hwnd
, 0, virtual_rect
.left
, virtual_rect
.top
,
154 virtual_rect
.right
- virtual_rect
.left
, virtual_rect
.bottom
- virtual_rect
.top
,
155 SWP_NOZORDER
| SWP_NOACTIVATE
| SWP_DEFERERASE
);
157 if (old_virtual_rect
.left
!= virtual_rect
.left
|| old_virtual_rect
.top
!= virtual_rect
.top
)
158 send_message_timeout( HWND_BROADCAST
, WM_X11DRV_DESKTOP_RESIZED
, old_virtual_rect
.left
,
159 old_virtual_rect
.top
, SMTO_ABORTIFHUNG
, 2000, FALSE
);
161 old_virtual_rect
= virtual_rect
;