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
*********************************************************/
20
* unityPlatformX11Settings.c --
22
* Handles saving and restoring various system settings that are needed for Unity to
28
#if !defined(VM_HAVE_X11_SS_EXT) && !defined(USING_AUTOCONF)
29
#error "We're not building with the X11 ScreenSaver extension."
34
*-----------------------------------------------------------------------------
36
* GetScreensaverActive --
38
* Finds out whether the screensaver is currently enabled.
41
* TRUE if successful, FALSE otherwise
44
* Stores the current setting in *currentSetting
46
*-----------------------------------------------------------------------------
50
GetScreensaverActive(UnityPlatform *up, // IN
51
Bool *currentSetting) // OUT
57
ASSERT(currentSetting);
59
*currentSetting = FALSE;
61
#if defined(VM_HAVE_X11_SS_EXT)
65
if (XScreenSaverQueryExtension(up->display, &eventBase, &errorBase)) {
66
XScreenSaverInfo saverInfo;
68
if (!XScreenSaverQueryInfo(up->display,
69
DefaultRootWindow(up->display),
74
*currentSetting = (saverInfo.state != ScreenSaverDisabled);
80
XGetScreenSaver(up->display, &timeout, &dummy, &dummy, &dummy);
86
*currentSetting = *currentSetting || (timeout ? TRUE : FALSE);
92
*-----------------------------------------------------------------------------
94
* SetScreensaverActive --
96
* Enables/disables the screensaver.
99
* TRUE if successful, FALSE otherwise
104
*-----------------------------------------------------------------------------
108
SetScreensaverActive(UnityPlatform *up, // IN
109
Bool currentSetting) // IN
111
int timeout = -1; // If XGetScreenSaver fails, use the default
113
int preferBlanking = DefaultBlanking;
114
int allowExposures = DefaultExposures;
115
char *xdgScreensaverPath;
120
* There are currently three ways to enable/disable the screensaver (in order of
121
* current preference):
123
* 1. The xdg-screensaver script that knows how to talk to the screensavers of most
125
* 2. XScreenSaverSuspend, via the X screensaver extension.
126
* 3. XSetScreenSaver.
128
* Only the first one actually works on most systems, but the other two are there to
129
* catch corner cases on odd systems.
132
xdgScreensaverPath = g_find_program_in_path("xdg-screensaver");
133
if (up->rootWindows && xdgScreensaverPath) {
134
char rootWindowID[64];
135
char *argv[] = {xdgScreensaverPath,
136
(char*)(currentSetting ? "resume" : "suspend"),
140
g_snprintf(rootWindowID, sizeof rootWindowID, "%#lx", up->rootWindows->windows[0]);
142
g_spawn_sync("/", argv, NULL, (GSpawnFlags)0, NULL, NULL, NULL, NULL, NULL, NULL);
144
g_free(xdgScreensaverPath);
146
#if defined(VM_HAVE_X11_SS_EXT)
151
if (!XScreenSaverQueryExtension(up->display, &eventBase, &errorBase)) {
155
* XScreenSaverSuspend is only available as of version 1.1 of the screensaver
158
# if (ScreenSaverMajorVersion > 1 \
159
|| (ScreenSaverMajorVersion == 1 && ScreenSaverMinorVersion >= 1))
164
if (XScreenSaverQueryVersion(up->display, &majorVersion, &minorVersion)
165
&& (majorVersion > 1 || (majorVersion == 1 && minorVersion >= 1))) {
167
XScreenSaverSuspend(up->display, !currentSetting);
168
up->currentSettings[UNITY_UI_SCREENSAVER] = currentSetting;
174
* XXX TODO: On systems that don't have XScreenSaverSuspend, we could always monitor
175
* ScreenSaverNotify events, and send a ForceScreenSaver request (with value of Reset)
176
* whenever the screensaver comes on.
181
XGetScreenSaver(up->display, &timeout, &interval, &preferBlanking, &allowExposures);
183
if (!currentSetting) {
184
up->savedScreenSaverTimeout = timeout; // Save the old timeout.
185
timeout = 0; // Disables the screensaver.
187
timeout = up->savedScreenSaverTimeout;
188
up->savedScreenSaverTimeout = -1;
191
XSetScreenSaver(up->display, timeout, interval, preferBlanking, allowExposures);
193
if (!currentSetting) {
195
* Disable the screen saver if it's already active.
197
XForceScreenSaver(up->display, ScreenSaverReset);
204
#ifdef VM_UNIMPLEMENTED_UNITY_SETTINGS
208
*-----------------------------------------------------------------------------
210
* GetDropShadowActive --
212
* Finds out whether drop shadows are currently enabled.
215
* TRUE if successful, FALSE otherwise
218
* Stores the current setting in *currentSetting
220
*-----------------------------------------------------------------------------
224
GetDropShadowActive(UnityPlatform *up, // IN
225
Bool *currentSetting) // OUT
228
ASSERT(currentSetting);
237
*-----------------------------------------------------------------------------
239
* SetDropShadowActive --
241
* Enables/disables drop shadows.
244
* TRUE if successful, FALSE otherwise
249
*-----------------------------------------------------------------------------
253
SetDropShadowActive(UnityPlatform *up, // IN
254
Bool currentSetting) // IN
258
up->currentSettings[UNITY_UI_DROP_SHADOW] = currentSetting;
267
*-----------------------------------------------------------------------------
269
* GetMenuAnimationActive --
271
* Finds out whether menu animation is currently enabled.
274
* TRUE if successful, FALSE otherwise
277
* Stores the current setting in *currentSetting
279
*-----------------------------------------------------------------------------
283
GetMenuAnimationActive(UnityPlatform *up, // IN
284
Bool *currentSetting) // OUT
287
ASSERT(currentSetting);
296
*-----------------------------------------------------------------------------
298
* SetMenuAnimationActive --
300
* Enables/disables the screensaver.
303
* TRUE if successful, FALSE otherwise
308
*-----------------------------------------------------------------------------
312
SetMenuAnimationActive(UnityPlatform *up, // IN
313
Bool currentSetting) // IN
317
up->currentSettings[UNITY_UI_MENU_ANIMATION] = currentSetting;
326
*-----------------------------------------------------------------------------
328
* GetTooltipAnimationActive --
330
* Finds out whether the screensaver is currently enabled.
333
* TRUE if successful, FALSE otherwise
336
* Stores the current setting in *currentSetting
338
*-----------------------------------------------------------------------------
342
GetTooltipAnimationActive(UnityPlatform *up, // IN
343
Bool *currentSetting) // OUT
346
ASSERT(currentSetting);
355
*-----------------------------------------------------------------------------
357
* SetTooltipAnimationActive --
359
* Enables/disables the screensaver.
362
* TRUE if successful, FALSE otherwise
367
*-----------------------------------------------------------------------------
371
SetTooltipAnimationActive(UnityPlatform *up, // IN
372
Bool currentSetting) // IN
376
up->currentSettings[UNITY_UI_TOOLTIP_ANIMATION] = currentSetting;
385
*-----------------------------------------------------------------------------
387
* GetWindowAnimationActive --
389
* Finds out whether the screensaver is currently enabled.
392
* TRUE if successful, FALSE otherwise
395
* Stores the current setting in *currentSetting
397
*-----------------------------------------------------------------------------
401
GetWindowAnimationActive(UnityPlatform *up, // IN
402
Bool *currentSetting) // OUT
405
ASSERT(currentSetting);
414
*-----------------------------------------------------------------------------
416
* SetWindowAnimationActive --
418
* Enables/disables the screensaver.
421
* TRUE if successful, FALSE otherwise
426
*-----------------------------------------------------------------------------
430
SetWindowAnimationActive(UnityPlatform *up, // IN
431
Bool currentSetting) // IN
435
up->currentSettings[UNITY_UI_WINDOW_ANIMATION] = currentSetting;
444
*-----------------------------------------------------------------------------
446
* GetFullWindowDragActive --
448
* Finds out whether the screensaver is currently enabled.
451
* TRUE if successful, FALSE otherwise
454
* Stores the current setting in *currentSetting
456
*-----------------------------------------------------------------------------
460
GetFullWindowDragActive(UnityPlatform *up, // IN
461
Bool *currentSetting) // OUT
464
ASSERT(currentSetting);
473
*-----------------------------------------------------------------------------
475
* SetFullWindowDragActive --
477
* Enables/disables the screensaver.
480
* TRUE if successful, FALSE otherwise
485
*-----------------------------------------------------------------------------
489
SetFullWindowDragActive(UnityPlatform *up, // IN
490
Bool currentSetting) // IN
494
up->currentSettings[UNITY_UI_FULL_WINDOW_DRAG] = currentSetting;
506
*-----------------------------------------------------------------------------
508
* GetTaskbarVisible --
510
* Shows or hides the taskbar as appropriate.
513
* TRUE if successful, FALSE otherwise.
518
*-----------------------------------------------------------------------------
522
GetTaskbarVisible(UnityPlatform *up, // IN
523
Bool *currentSetting) // OUT
525
UnityPlatformWindow **allWindows;
530
ASSERT(currentSetting);
533
HashTable_ToArray(up->allWindows,
534
(void ***)&allWindows,
538
Debug("Couldn't find any listed windows for taskbar visibility detection.\n");
539
return FALSE; // We haven't yet populated the window list for some reason
543
* Hunt through all the windows for ones that are of type DOCK.
545
*currentSetting = FALSE;
546
for (i = 0; i < numWindows; i++) {
547
if (UNITY_WINDOW_TYPE_DOCK == allWindows[i]->windowType
548
&& allWindows[i]->isViewable) {
549
*currentSetting = TRUE;
561
*-----------------------------------------------------------------------------
563
* UnityPlatformSetTaskbarVisible --
565
* Shows or hides the taskbar as appropriate.
568
* TRUE if successful, FALSE otherwise.
571
* Shows or hides task bar.
573
*-----------------------------------------------------------------------------
577
UnityPlatformSetTaskbarVisible(UnityPlatform *up, // IN
578
Bool currentSetting) // IN
580
UnityPlatformWindow **allWindows;
586
up->needTaskbarSetting = FALSE;
588
up->currentSettings[UNITY_UI_TASKBAR_VISIBLE] = currentSetting;
591
HashTable_ToArray(up->allWindows,
592
(void ***) &allWindows,
596
* Hunt through all the windows for ones that are of type DOCK.
598
for (i = 0; i < numWindows; i++) {
599
if (UNITY_WINDOW_TYPE_DOCK == allWindows[i]->windowType) {
601
UnityPlatformWindow *upw = allWindows[i];
603
dockWindow = upw->clientWindow;
605
dockWindow = upw->toplevelWindow;
608
if (currentSetting) {
610
* If this flag is still set, that means that this window is being
611
* remapped -before- we received a _NET_WM_DESKTOP PropertyDelete
612
* notification. (One such case may be if exiting Unity before the
613
* PropertyDelete is delivered.) In that case, we'll go ahead and
614
* reset the property ourselves before remapping.
616
if (upw->wantSetDesktopNumberOnUnmap) {
617
UPWindow_SetEWMHDesktop(up, upw, upw->onUnmapDesktopNumber);
618
upw->wantSetDesktopNumberOnUnmap = FALSE;
620
XMapWindow(up->display, dockWindow);
622
/* Preserve _NET_WM_DESKTOP across unmap. */
623
if (!upw->wantSetDesktopNumberOnUnmap) {
624
upw->wantSetDesktopNumberOnUnmap = TRUE;
625
upw->onUnmapDesktopNumber = upw->desktopNumber;
627
XWithdrawWindow(up->display, dockWindow, 0);
630
UPWindow_CheckRelevance(up, upw, NULL);
638
* We need to repeat this call later.
640
up->needTaskbarSetting = TRUE;
648
*-----------------------------------------------------------------------------
650
* SaveVirtualDesktopSettings --
652
* Saves the current virtual desktop configuration so it can be restored later on.
660
*-----------------------------------------------------------------------------
664
SaveVirtualDesktopSettings(UnityPlatform *up) // IN
668
up->desktopInfo.savedNumDesktops = UnityPlatformGetNumVirtualDesktops(up);
669
UnityPlatformGetVirtualDesktopLayout(up, up->desktopInfo.savedLayoutData);
670
up->desktopInfo.savedCurrentDesktop = UnityX11GetCurrentDesktop(up);
675
*-----------------------------------------------------------------------------
677
* RestoreVirtualDesktopSettings --
679
* Restores the saved virtual desktop configuration.
685
* Guest's virtual desktop config may be changed.
687
*-----------------------------------------------------------------------------
691
RestoreVirtualDesktopSettings(UnityPlatform *up) // IN
696
memcpy(up->desktopInfo.layoutData,
697
up->desktopInfo.savedLayoutData,
698
sizeof up->desktopInfo.layoutData);
699
tempDesktops = up->desktopInfo.numDesktops;
700
up->desktopInfo.numDesktops = up->desktopInfo.savedNumDesktops;
701
UnityPlatformSyncDesktopConfig(up);
704
* ...because numDesktops also refers to the size of the guestDesktopToUnity and
705
* unityDesktopToGuest arrays.
707
up->desktopInfo.numDesktops = tempDesktops;
709
UnityX11SetCurrentDesktop(up, up->desktopInfo.savedCurrentDesktop);
714
*-----------------------------------------------------------------------------
716
* UnityPlatformSaveSystemSettings --
718
* Stub to make unity.c happy. This function is called at a very inconvenient time
719
* for the X11 port, so I just call its UnityX11 equivalent at the appropriate point
720
* in StartHelperThreads instead.
728
*-----------------------------------------------------------------------------
732
UnityPlatformSaveSystemSettings(UnityPlatform *up) // IN
738
*----------------------------------------------------------------------------
740
* UnityX11SaveSystemSettings --
742
* Save and disable certain system settings here:
743
* a. If a screen saver is enabled, disable it
744
* b. If animation for menus or tooltips is enabled, disable it
745
* c. If menu shading is enabled, disable it
746
* d. If full window drag is disabled, enable it
747
* e. If window animation is enabled, disable it
748
* f. Hide the task bar.
750
* Right now on X11, only the screensaver and task bar make any sense.
752
* Remember all the settings changed above in a bit mask,
753
* so we can restore them later when the user exits
756
* Note, that the system ui changes made here will not
757
* persist after the system reboot.
763
* A bunch of system ui settings might be changed.
765
*----------------------------------------------------------------------------
769
UnityX11SaveSystemSettings(UnityPlatform *up) // IN
774
* We only want to remember current settings if we do not have saved settings already.
775
* One of the reasons why we might have saved settings already is because we are
776
* re-entering unity without cleanly exiting it first (if the VM was suspended). In
777
* this case, theoretically, all the right settings are set already and
778
* up->originalSettings contains the original user settings that we do not want to
781
if (!up->haveOriginalSettings) {
782
Bool *originalSettings = up->originalSettings;
784
memset(up->originalSettings, 0, sizeof up->originalSettings);
786
if (!GetScreensaverActive(up, &originalSettings[UNITY_UI_SCREENSAVER])) {
787
originalSettings[UNITY_UI_SCREENSAVER] = TRUE;
790
#ifdef VM_UNIMPLEMENTED_UNITY_SETTINGS
791
if (!GetDropShadowActive(up, &originalSettings[UNITY_UI_DROP_SHADOW])) {
792
originalSettings[UNITY_UI_DROP_SHADOW] = TRUE;
795
if (!GetMenuAnimationActive(up, &originalSettings[UNITY_UI_MENU_ANIMATION])) {
796
originalSettings[UNITY_UI_MENU_ANIMATION] = TRUE;
799
if (!GetTooltipAnimationActive(up,
800
&originalSettings[UNITY_UI_TOOLTIP_ANIMATION])) {
801
originalSettings[UNITY_UI_TOOLTIP_ANIMATION] = TRUE;
804
if (!GetWindowAnimationActive(up, &originalSettings[UNITY_UI_WINDOW_ANIMATION])) {
805
originalSettings[UNITY_UI_WINDOW_ANIMATION] = TRUE;
808
if (!GetFullWindowDragActive(up, &originalSettings[UNITY_UI_FULL_WINDOW_DRAG])) {
809
originalSettings[UNITY_UI_FULL_WINDOW_DRAG] = TRUE;
813
if (!GetTaskbarVisible(up, &originalSettings[UNITY_UI_TASKBAR_VISIBLE])) {
814
originalSettings[UNITY_UI_TASKBAR_VISIBLE] = TRUE;
817
SaveVirtualDesktopSettings(up);
819
up->haveOriginalSettings = TRUE;
821
memcpy(up->currentSettings, originalSettings, sizeof up->currentSettings);
824
SetScreensaverActive(up, FALSE);
825
#ifdef VM_UNIMPLEMENTED_UNITY_SETTINGS
826
SetDropShadowActive(up, FALSE);
827
SetMenuAnimationActive(up, FALSE);
828
SetTooltipAnimationActive(up, FALSE);
829
SetWindowAnimationActive(up, FALSE);
830
SetFullWindowDragActive(up, FALSE);
836
Bool shouldBeVisible = FALSE;
838
if (!RpcOut_sendOne(&reply, &replyLen, UNITY_RPC_VMX_SHOW_TASKBAR)) {
839
Debug("%s: could not get the VMX show taskbar setting, assuming FALSE\n",
844
if (StrUtil_StrToUint(&value, reply)) {
845
shouldBeVisible = (value == 0) ? FALSE : TRUE;
849
Debug("TASKBAR SHOULD BE VISIBLE: %d\n", shouldBeVisible);
851
UnityPlatformSetTaskbarVisible(up, shouldBeVisible);
859
*-----------------------------------------------------------------------------
861
* UnityPlatformRestoreSystemSettings --
863
* Stub to make unity.c happy. This function is called at a very inconvenient time
864
* for the X11 port, so I just call its UnityX11 equivalent at the appropriate point
865
* in KillHelperThreads instead.
873
*-----------------------------------------------------------------------------
877
UnityPlatformRestoreSystemSettings(UnityPlatform *up) // IN
883
*----------------------------------------------------------------------------
885
* UnityX11RestoreSystemSettings --
887
* Restore system ui settings to what they used to be
888
* before we entered unity mode.
891
* a. Enable screen saver if it was disabled
892
* b. Enable menu and tool tip animation if it was disabled
893
* c. Enable menu shading is enabled if it was disabled
894
* d. Disable full window drag is disabled if it was enabled
895
* e. Enable window animation if it was disabled
896
* f. Show the task bar if it was hidden
902
* A bunch of system ui settings might be changed.
904
*----------------------------------------------------------------------------
908
UnityX11RestoreSystemSettings(UnityPlatform *up) // IN
912
Debug("UnityPlatformRestoreSystemSettings\n");
913
if (up->currentSettings[UNITY_UI_SCREENSAVER]
914
!= up->originalSettings[UNITY_UI_SCREENSAVER]) {
915
SetScreensaverActive(up, up->originalSettings[UNITY_UI_SCREENSAVER]);
916
Debug("%s: Restored screen saver\n", __FUNCTION__);
919
#ifdef VM_UNIMPLEMENTED_UNITY_SETTINGS
920
if (up->currentSettings[UNITY_UI_DROP_SHADOW]
921
!= up->originalSettings[UNITY_UI_DROP_SHADOW]) {
922
SetDropShadowActive(up, up->originalSettings[UNITY_UI_DROP_SHADOW]);
923
Debug("%s: Restored drop shadows\n", __FUNCTION__);
926
if (up->currentSettings[UNITY_UI_MENU_ANIMATION]
927
!= up->originalSettings[UNITY_UI_MENU_ANIMATION]) {
928
SetMenuAnimationActive(up, up->originalSettings[UNITY_UI_MENU_ANIMATION]);
929
Debug("%s: Restored menu animation\n", __FUNCTION__);
932
if (up->currentSettings[UNITY_UI_TOOLTIP_ANIMATION]
933
!= up->originalSettings[UNITY_UI_TOOLTIP_ANIMATION]) {
934
SetTooltipAnimationActive(up, up->originalSettings[UNITY_UI_TOOLTIP_ANIMATION]);
935
Debug("%s: Restored tool tip animation\n", __FUNCTION__);
938
if (up->currentSettings[UNITY_UI_WINDOW_ANIMATION]
939
!= up->originalSettings[UNITY_UI_WINDOW_ANIMATION]) {
940
SetWindowAnimationActive(up, up->originalSettings[UNITY_UI_WINDOW_ANIMATION]);
941
Debug("%s: Restored window animation\n", __FUNCTION__);
944
if (up->currentSettings[UNITY_UI_FULL_WINDOW_DRAG]
945
!= up->originalSettings[UNITY_UI_FULL_WINDOW_DRAG]) {
946
SetFullWindowDragActive(up, up->originalSettings[UNITY_UI_FULL_WINDOW_DRAG]);
947
Debug("%s: Restored outline drag.\n", __FUNCTION__);
951
if (up->currentSettings[UNITY_UI_TASKBAR_VISIBLE]
952
!= up->originalSettings[UNITY_UI_TASKBAR_VISIBLE]) {
953
UnityPlatformSetTaskbarVisible(up, up->originalSettings[UNITY_UI_TASKBAR_VISIBLE]);
954
Debug("%s: Restored taskbar visibility.\n", __FUNCTION__);
957
RestoreVirtualDesktopSettings(up);
960
* The user's settings have been restored, which means the originalSettings info will
961
* not be relevant next time we go into SaveSystemSettings().
963
up->haveOriginalSettings = FALSE;
968
*----------------------------------------------------------------------------
970
* UnityPlatformShowTaskbar --
972
* Show/hide the taskbar while in Unity mode.
980
*----------------------------------------------------------------------------
984
UnityPlatformShowTaskbar(UnityPlatform *up, // IN
985
Bool showTaskbar) // IN
990
* If we are in Unity mode, we need to hide/show the taskbar.
991
* If the user asked to show the taskbar and the taskbar was previously hidden,
992
* we need to show the taskbar and readjust the work area.
993
* Other cases (when the taskbar is already shown and user wants to show it,
994
* for example), should theoretically never happen, but if they do, we just
995
* ignore them because there's not much we can do.
998
if (UnityPlatformIsUnityRunning(up)) {
999
Debug("Host asked us to show the taskbar %d\n", showTaskbar);
1000
UnityPlatformSetTaskbarVisible(up, showTaskbar);
1002
Debug("%s: We are not in Unity mode, ignore the show taskbar command\n",
1006
UnityPlatformDoUpdate(up, TRUE);
1011
*-----------------------------------------------------------------------------
1013
* UnityPlatformShowDesktop --
1015
* Show/hide the entire VM desktop while in Unity mode.
1023
*-----------------------------------------------------------------------------
1027
UnityPlatformShowDesktop(UnityPlatform *up, // IN
1028
Bool showDesktop) // IN