1
/*********************************************************
2
* Copyright (C) 2007-2008 VMware, Inc. All rights reserved.
4
* This program is free software; you can redistribute it and/or modify it
5
* under the terms of the GNU Lesser General Public License as published
6
* by the Free Software Foundation version 2.1 and no later version.
8
* This program is distributed in the hope that it will be useful, but
9
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
10
* or FITNESS FOR A PARTICULAR PURPOSE. See the Lesser GNU General Public
11
* License for more details.
13
* You should have received a copy of the GNU Lesser General Public License
14
* along with this program; if not, write to the Free Software Foundation, Inc.,
15
* 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
17
*********************************************************/
22
* Internal state shared between the various modules that implement Unity for X11.
29
* It's necessary to include glib, gtk+, and Xlib before the rest of the header files,
30
* and then #undef bool. This is because Xlib has '#define Bool int', while
31
* vm_basic_types.h has 'typedef char Bool;'.
34
#include "vmware/tools/unity/windowPathFactory.hh"
42
#include <X11/Xatom.h>
43
#include <X11/Xutil.h>
44
#include <X11/extensions/scrnsaver.h>
45
#if defined(ScreenSaverMajorVersion) && defined(ScreenSaverMinorVersion)
46
#define VM_HAVE_X11_SS_EXT 1
48
#include <X11/extensions/shape.h>
49
#if defined(ShapeNumberEvents)
50
#define VM_HAVE_X11_SHAPE_EXT 1
55
#include "vmware/tools/guestrpc.h"
59
#include "unityCommon.h"
60
#include "unityPlatform.h"
72
* Warn builders up front that GTK 2 is mandatory.
75
# error UnityX11 depends on GTK+ 2.
80
* These defines are listed in the EWMH spec, but not available in any header file that I
83
#ifndef _NET_WM_ORIENTATION_HORZ
84
#define _NET_WM_ORIENTATION_HORZ 0
85
#define _NET_WM_ORIENTATION_VERT 1
87
#define _NET_WM_TOPLEFT 0
88
#define _NET_WM_TOPRIGHT 1
89
#define _NET_WM_BOTTOMRIGHT 2
90
#define _NET_WM_BOTTOMLEFT 3
92
#define _NET_WM_STATE_REMOVE 0
93
#define _NET_WM_STATE_ADD 1
97
* These describe system settings saved when entering Unity mode, and restored upon
101
UNITY_UI_SCREENSAVER,
102
UNITY_UI_TASKBAR_VISIBLE,
103
#ifdef VM_UNIMPLEMENTED_UNITY_SETTINGS
104
UNITY_UI_DROP_SHADOW,
105
UNITY_UI_MENU_ANIMATION,
106
UNITY_UI_TOOLTIP_ANIMATION,
107
UNITY_UI_WINDOW_ANIMATION,
108
UNITY_UI_FULL_WINDOW_DRAG,
111
UNITY_UI_MAX_SETTINGS
115
UNITY_X11_WM__NET_MOVERESIZE_WINDOW,
116
UNITY_X11_WM__NET_CLOSE_WINDOW,
117
UNITY_X11_WM__NET_RESTACK_WINDOW,
118
UNITY_X11_WM__NET_ACTIVE_WINDOW,
119
UNITY_X11_WM__NET_WM_ACTION_MINIMIZE,
120
UNITY_X11_WM__NET_WM_ACTION_CLOSE,
121
UNITY_X11_WM__NET_WM_ACTION_SHADE,
122
UNITY_X11_WM__NET_WM_ACTION_STICK,
123
UNITY_X11_WM__NET_WM_ACTION_FULLSCREEN,
124
UNITY_X11_WM__NET_WM_ACTION_MAXIMIZE_HORZ,
125
UNITY_X11_WM__NET_WM_ACTION_MAXIMIZE_VERT,
126
UNITY_X11_WM__NET_FRAME_EXTENTS,
127
UNITY_X11_WM__NET_WM_STRUT_PARTIAL,
128
UNITY_X11_WM__NET_WM_STATE_HIDDEN,
129
UNITY_X11_WM__NET_WM_STATE_MINIMIZED,
131
UNITY_X11_MAX_WM_PROTOCOLS
132
} UnityX11WMProtocol;
135
UNITY_X11_WIN_WM_DELETE_WINDOW,
136
UNITY_X11_MAX_WIN_PROTOCOLS
137
} UnityX11WinProtocol;
141
* UnitySpecialWindow objects track windows that need special treatment, including root
142
* windows and windows that we create.
144
typedef struct UnitySpecialWindow UnitySpecialWindow;
145
typedef void (*UnitySpecialEventHandler)(UnityPlatform *up,
146
UnitySpecialWindow *usw,
147
const XEvent *xevent,
148
Window realEventWindow);
150
struct UnitySpecialWindow {
151
UnitySpecialEventHandler evHandler;
154
Bool windowsAreOwned;
157
typedef struct UnityPlatformWindow UnityPlatformWindow;
161
* Custom Glib source to monitor the Xlib queue and X11 socket(s).
163
* This structure is "derived from" GSource. It will be recast and used as
164
* a GSource with Glib functions.
168
GSource base; ///< Owned by Glib. Hands off!
169
UnityPlatform *up; ///< Our running UnityPlatform context.
170
GHashTable *fdTable; ///< file descriptor => GPollFD *.
175
* Holds platform-specific data.
177
struct _UnityPlatform {
178
Display *display; // X11 display object
179
long eventTimeDiff; // Diff between X server time and our local time
181
* Integrates Unity event sources with the Glib main loop.
183
* Monitors dedicated Unity X11 socket(s) and the associated Xlib event
184
* queue. Its lifetime is for the duration that the user is in Unity mode.
187
* The event source is created in UnityPlatformStartHelperThreads and torn
188
* down in UnityPlatformKillHelperThreads.
190
UnityGSource *glibSource;
192
struct { // Atoms that we'll find useful
193
Atom _NET_WM_WINDOW_TYPE,
194
_NET_WM_WINDOW_TYPE_DESKTOP,
195
_NET_WM_WINDOW_TYPE_DOCK,
196
_NET_WM_WINDOW_TYPE_TOOLBAR,
197
_NET_WM_WINDOW_TYPE_TOOLTIP,
198
_NET_WM_WINDOW_TYPE_DROPDOWN_MENU,
199
_NET_WM_WINDOW_TYPE_POPUP_MENU,
200
_NET_WM_WINDOW_TYPE_MENU,
201
_NET_WM_WINDOW_TYPE_UTILITY,
202
_NET_WM_WINDOW_TYPE_SPLASH,
203
_NET_WM_WINDOW_TYPE_DIALOG,
204
_NET_WM_WINDOW_TYPE_NORMAL,
205
_NET_WM_WINDOW_TYPE_DND,
206
_NET_WM_ALLOWED_ACTIONS,
208
_NET_WM_ACTION_RESIZE,
209
_NET_WM_ACTION_MINIMIZE,
210
_NET_WM_ACTION_SHADE,
211
_NET_WM_ACTION_STICK,
212
_NET_WM_ACTION_MAXIMIZE_HORZ,
213
_NET_WM_ACTION_MAXIMIZE_VERT,
214
_NET_WM_ACTION_FULLSCREEN,
215
_NET_WM_ACTION_CHANGE_DESKTOP,
216
_NET_WM_ACTION_CLOSE,
218
_NET_WM_STATE_HIDDEN,
220
_NET_WM_STATE_STICKY,
221
_NET_WM_STATE_MINIMIZED,
222
_NET_WM_STATE_MAXIMIZED_HORZ,
223
_NET_WM_STATE_MAXIMIZED_VERT,
224
_NET_WM_STATE_SHADED,
225
_NET_WM_STATE_SKIP_TASKBAR,
226
_NET_WM_STATE_SKIP_PAGER,
227
_NET_WM_STATE_FULLSCREEN,
230
_NET_WM_STATE_DEMANDS_ATTENTION,
232
_NET_WM_USER_TIME_WINDOW,
237
_NET_MOVERESIZE_WINDOW,
240
_NET_WM_STRUT_PARTIAL,
241
_NET_NUMBER_OF_DESKTOPS,
243
_NET_CURRENT_DESKTOP,
260
UnityWindowTracker *tracker;
261
UnityHostCallbacks hostCallbacks;
264
* This tracks all toplevel windows, whether or not they are showing through to the
265
* window tracker. It also has entries for client windows (which point to the same
266
* UnityPlatformWindow objects).
268
HashTable *allWindows;
269
UnityPlatformWindow *topWindow; // For tracking Z-ordering
272
* This tracks "special" windows, including root windows, the DnD detection window,
273
* and the work area-faking window(s). It's mainly used to make sure these windows
274
* get proper event handling.
276
HashTable *specialWindows;
277
UnitySpecialWindow *rootWindows;
279
UnityPlatformWindow *desktopWindow;
282
UnitySpecialWindow *workAreas;
284
UnityRect *needWorkAreas;
285
int needNumWorkAreas;
289
* Hopefully, most of the time the desktopIDs on host and guest
290
* will be the same, but we can't count on it, so these two arrays
291
* translate back and forth between guest and unity desktop IDs.
293
UnityDesktopId *guestDesktopToUnity;
294
uint32 *unityDesktopToGuest;
299
Atom savedLayoutData[4];
300
size_t savedNumDesktops;
301
uint32 savedCurrentDesktop;
302
uint32 currentDesktop;
304
* Set by the set.desktop.active RPC to indicate which desktop the host is in
305
* when we enter Unity.
307
uint32 initialDesktop;
308
#define UNITY_X11_INITIALDESKTOP_UNSET MAX_UINT32
312
Bool stackingChanged;
314
Bool haveOriginalSettings;
315
Bool currentSettings[UNITY_UI_MAX_SETTINGS];
316
Bool originalSettings[UNITY_UI_MAX_SETTINGS];
317
Bool needTaskbarSetting;
319
int savedScreenSaverTimeout;
321
Bool wmProtocols[UNITY_X11_MAX_WM_PROTOCOLS];
326
vmware::tools::unity::WindowPathFactory* wpFactory;
330
* Holds per-window platform-specific data.
333
struct UnityPlatformWindow {
337
* In X11, we want to watch both the top-level window (normally created by the window
338
* manager) and the application's window. The UnityWindowId will correspond to the
339
* former - to save lookups later, we track both of them here, as well as their root
342
Window toplevelWindow;
347
int onUnmapDesktopNumber; ///< @sa wantSetDesktopNumberOnUnmap
348
UnityPlatformWindow *higherWindow;
349
UnityPlatformWindow *lowerWindow;
351
UnityWindowType windowType;
359
Bool windowProtocols[UNITY_X11_MAX_WIN_PROTOCOLS];
361
Bool isRelevant; // Whether the window is relayed through the window tracker
362
Bool isOverrideRedirect; // Allow detecting changes in this attr
367
* Indicates we wish to force a value of _NET_CURRENT_DESKTOP across XUnmapWindow.
369
* When we unmap a window, its _NET_CURRENT_DESKTOP property is cleared. There are
370
* some circumstances in which this behavior is undesirable. (E.g., once we hide
371
* the KDE taskbar, it will only appear on desktop #0 after exiting Unity, as KDE
372
* doesn't automatically remap panel/dock windows as sticky windows.)
374
* Setting this flag (in combination with setting onUnmapDesktopNumber) causes
375
* us to reset the _NET_CURRENT_DESKTOP property in response to receiving its
376
* PropertyDelete. If a PropertyNewValue arrives before the -Delete, we'll query
377
* and record the new value into onUnmapDesktopNumber (if the property exists).
379
Bool wantSetDesktopNumberOnUnmap;
382
* Mini state-machine:
384
* isMaximized, isMinimized, and isHidden can all be set or unset independently
385
* from the host's perspective.
387
* isMaximized can pretty much be set independently.
388
* Leaving isHidden requires WM_HINTS to be set correctly.
389
* Entering isHidden requires XWithdrawWindow.
390
* If !isHidden, !isMinimized -> isMinimized requires XIconifyWindow()
391
* If !isHidden, isMinimized -> !isMinimized requires just mapping the window.
398
* When a client window is reparented by a window manager, a ReparentNotify event
399
* is generated. We're interested in this event, because it tells us that the
400
* relationship between this UnityPlatformWindow and its top-level and client
401
* windows has changed.
403
* Per ICCCM §4.1.3.1, we identify the client window as the window within a
404
* tree possessing the WM_STATE property. Unfortunately, this property may
405
* not yet be set when we receive ReparentNotify. If that's the case, this flag
406
* is raised such that once we do see a WM_STATE change related to one of
407
* our windows (via a PropertyNotify event), we may act accordingly.
409
Bool waitingForWmState;
412
* It isn't safe to delete a UnityPlatformWindow object in the guts of the
413
* event processing code. (Example: processing a DestroyNotify event or
414
* learning that a window is irrelevant to Unity/X11.) Unfortunately, other
415
* parts of this codebase don't use the ref counting scheme correctly, so
416
* this hack will simply mark a UPW for deletion, and the outermost event
417
* entry point will take care of deleting if set.
419
* XXX Ditch this flag and instead make use of the reference counting
425
* See wm-spec::_NET_FRAME_EXTENTS.
427
uint32 frameExtents[4];
431
* Implemented by unityPlatformX11Window.c
433
void UPWindow_ProcessEvent(UnityPlatform *up,
434
UnityPlatformWindow *upw,
435
Window realEventWindow,
436
const XEvent *xevent);
437
UnityPlatformWindow *UPWindow_Create(UnityPlatform *up, Window window);
438
void UPWindow_CheckRelevance(UnityPlatform *up,
439
UnityPlatformWindow *upw,
440
const XEvent *motivator);
441
void UPWindow_Ref(UnityPlatform *up, UnityPlatformWindow *upw);
442
void UPWindow_Restack(UnityPlatform *up, UnityPlatformWindow *upw, Window above);
443
void UPWindow_Unref(UnityPlatform *up, UnityPlatformWindow *upw);
444
Bool UPWindow_ProtocolSupported(const UnityPlatform *up,
445
const UnityPlatformWindow *upw,
446
UnityX11WinProtocol proto);
447
UnityPlatformWindow *UPWindow_Lookup(UnityPlatform *up, Window window);
448
void UPWindow_SetUserTime(UnityPlatform *up,
449
UnityPlatformWindow *upw);
450
void UPWindow_SetEWMHDesktop(UnityPlatform *up,
451
UnityPlatformWindow *upw,
452
uint32 ewmhDesktopId);
455
* Implemented by unityPlatformX11.c
457
Bool UnityPlatformWMProtocolSupported(UnityPlatform *up, UnityX11WMProtocol proto);
458
Bool UnityPlatformIsRootWindow(UnityPlatform *up, Window window);
459
uint32 UnityX11GetCurrentDesktop(UnityPlatform *up);
460
void UnityX11SetCurrentDesktop(UnityPlatform *up, uint32 currentDesktop);
461
Time UnityPlatformGetServerTime(UnityPlatform *up);
463
#define UnityPlatformProcessMainLoop() g_main_context_iteration(NULL, TRUE)
465
int UnityPlatformGetErrorCount(UnityPlatform *up);
466
void UnityPlatformResetErrorCount(UnityPlatform *up);
467
Bool UnityPlatformSetTaskbarVisible(UnityPlatform *up, Bool currentSetting);
468
void UnityPlatformSendClientMessage(UnityPlatform *up, Window destWindow,
469
Window w, Atom messageType,
470
int format, int numItems, const void *data);
471
void UnityPlatformSyncDesktopConfig(UnityPlatform *up);
472
void UnityX11SaveSystemSettings(UnityPlatform *up);
473
void UnityX11RestoreSystemSettings(UnityPlatform *up);
474
size_t UnityPlatformGetNumVirtualDesktops(UnityPlatform *up);
475
void UnityPlatformGetVirtualDesktopLayout(UnityPlatform *up, Atom *layoutData);
476
const char *UnityPlatformGetEventString(UnityPlatform *up, int type);
478
gboolean UnityX11HandleEvents(gpointer data);
482
* Implemented in x11Event.c.
485
void UnityX11EventEstablishSource(UnityPlatform *up);
486
void UnityX11EventTeardownSource(UnityPlatform *up);
490
* Implemented in x11Util.c.
493
Bool UnityX11Util_IsWindowDecorationWidget(UnityPlatform *up,