. Unity: Add {un,}stick window RPC handlers.
. Complain loudly if res set or topology set is called at wrong state.
Signed-off-by: Marcelo Vanzin <mvanzin@vmware.com>
static char *FilePosixNearestExistingAncestor(char const *path);
# ifdef VMX86_SERVER
-#define VMFS2CONST 456
#define VMFS3CONST 256
#include "hostType.h"
/* Needed for VMFS implementation of File_GetFreeSpace() */
*
* Check if the given file is on a VMFS supports such a file size
*
- * In the case of VMFS2, the largest supported file size is
- * 456 * 1024 * B bytes
- *
* In the case of VMFS3/4, the largest supported file size is
* 256 * 1024 * B bytes
*
}
if (strcmp(fsType, "VMFS") == 0) {
- if (version == 2) {
- maxFileSize = (VMFS2CONST * (uint64) blockSize * 1024);
- } else if (version >= 3) {
+ if (version >= 3) {
/* Get ready for VMFS4 and perform sanity check on version */
ASSERT(version == 3 || version == 4);
maxFileSize = (VMFS3CONST * (uint64) blockSize * 1024);
- }
+ }
if (fileSize <= maxFileSize && maxFileSize != -1) {
free(fsType);
len = walk - begin;
*next = myNext;
- return ((int) len);
+ return (int) len;
}
VIX_E_LICENSE = 32,
VIX_E_VM_HOST_DISCONNECTED = 34,
VIX_E_AUTHENTICATION_FAIL = 35,
+ VIX_E_HOST_CONNECTION_LOST = 36,
/* Handle Errors */
VIX_E_INVALID_HANDLE = 1000,
{ UNITY_RPC_WINDOW_UNMINIMIZE, UnityPlatformUnminimizeWindow },
{ UNITY_RPC_WINDOW_MAXIMIZE, UnityPlatformMaximizeWindow },
{ UNITY_RPC_WINDOW_UNMAXIMIZE, UnityPlatformUnmaximizeWindow },
+ { UNITY_RPC_WINDOW_STICK, UnityPlatformStickWindow },
+ { UNITY_RPC_WINDOW_UNSTICK, UnityPlatformUnstickWindow },
/* Add more commands and handlers above this. */
{ NULL, NULL }
};
*/
if (Unity_IsSupported()) {
+ UnityCommandElem *elem;
+
RpcIn_RegisterCallback(rpcIn, UNITY_RPC_ENTER, UnityTcloEnter, NULL);
RpcIn_RegisterCallback(rpcIn, UNITY_RPC_GET_UPDATE_FULL, UnityTcloGetUpdate, NULL);
RpcIn_RegisterCallback(rpcIn, UNITY_RPC_GET_UPDATE_INCREMENTAL,
UnityTcloGetWindowPath, NULL);
RpcIn_RegisterCallback(rpcIn, UNITY_RPC_WINDOW_SETTOP,
UnityTcloSetTopWindowGroup, NULL);
- RpcIn_RegisterCallback(rpcIn, UNITY_RPC_WINDOW_CLOSE,
- UnityTcloWindowCommand, NULL);
RpcIn_RegisterCallback(rpcIn, UNITY_RPC_GET_WINDOW_CONTENTS,
UnityTcloGetWindowContents, NULL);
RpcIn_RegisterCallback(rpcIn, UNITY_RPC_GET_ICON_DATA,
RpcIn_RegisterCallback(rpcIn, UNITY_RPC_EXIT, UnityTcloExit, NULL);
RpcIn_RegisterCallback(rpcIn, UNITY_RPC_WINDOW_MOVE_RESIZE,
UnityTcloMoveResizeWindow, NULL);
- RpcIn_RegisterCallback(rpcIn, UNITY_RPC_WINDOW_SHOW,
- UnityTcloWindowCommand, NULL);
- RpcIn_RegisterCallback(rpcIn, UNITY_RPC_WINDOW_HIDE,
- UnityTcloWindowCommand, NULL);
- RpcIn_RegisterCallback(rpcIn, UNITY_RPC_WINDOW_MINIMIZE,
- UnityTcloWindowCommand, NULL);
- RpcIn_RegisterCallback(rpcIn, UNITY_RPC_WINDOW_UNMINIMIZE,
- UnityTcloWindowCommand, NULL);
- RpcIn_RegisterCallback(rpcIn, UNITY_RPC_WINDOW_MAXIMIZE,
- UnityTcloWindowCommand, NULL);
- RpcIn_RegisterCallback(rpcIn, UNITY_RPC_WINDOW_UNMAXIMIZE,
- UnityTcloWindowCommand, NULL);
RpcIn_RegisterCallback(rpcIn, UNITY_RPC_DESKTOP_CONFIG_SET,
UnityTcloSetDesktopConfig, NULL);
RpcIn_RegisterCallback(rpcIn, UNITY_RPC_DESKTOP_ACTIVE_SET,
UnityTcloSetDesktopActive, NULL);
RpcIn_RegisterCallback(rpcIn, UNITY_RPC_WINDOW_DESKTOP_SET,
UnityTcloSetWindowDesktop, NULL);
+
+ /*
+ * Handle all of the UnityTcloWindowCommand RPCs at once.
+ */
+ for (elem = unityCommandTable; elem->name != NULL; elem++) {
+ RpcIn_RegisterCallback(rpcIn, elem->name, UnityTcloWindowCommand,
+ NULL);
+ }
}
}
Bool UnityPlatformSetWindowDesktop(UnityPlatform *up,
UnityWindowId windowId,
UnityDesktopId desktopId);
+Bool UnityPlatformStickWindow(UnityPlatform *up,
+ UnityWindowId windowId);
+Bool UnityPlatformUnstickWindow(UnityPlatform *up,
+ UnityWindowId windowId);
Bool UnityPlatformIsUnityRunning(UnityPlatform *up);
Bool UnityPlatformStartHelperThreads(UnityPlatform *up);
void UnityPlatformKillHelperThreads(UnityPlatform *up);
int numItems,
const void *data);
+static Bool GetRelevantWMWindow(UnityPlatform *up,
+ UnityWindowId windowId,
+ Window *wmWindow);
+static Bool SetWindowStickiness(UnityPlatform *up,
+ UnityWindowId windowId,
+ Bool wantSticky);
+
static const GuestCapabilities platformUnityCaps[] = {
UNITY_CAP_WORK_AREA,
UNITY_CAP_START_MENU,
UNITY_CAP_MULTI_MON,
- UNITY_CAP_VIRTUAL_DESK
+ UNITY_CAP_VIRTUAL_DESK,
+ UNITY_CAP_STICKY_WINDOWS,
};
/*
*/
{
GIOChannel *unityDisplayChannel;
+
unityDisplayChannel = g_io_channel_unix_new(ConnectionNumber(up->display));
+ if (g_io_channel_set_encoding(unityDisplayChannel, NULL, NULL) !=
+ G_IO_STATUS_NORMAL) {
+ Warning("%s: Unable to switch Unity I/O channel from UTF-8 to raw data.\n",
+ __func__);
+ }
+
up->unityDisplayWatchID = g_io_add_watch(unityDisplayChannel,
G_IO_IN | G_IO_ERR | G_IO_HUP | G_IO_NVAL,
UnityPlatformHandleEventsGlib,
unityPt->y = localPt->y;
}
+
+/*
+ ******************************************************************************
+ * UnityPlatformStickWindow -- */ /**
+ *
+ * @brief "Stick" a window to the desktop.
+ *
+ * @param[in] up Platform context.
+ * @param[in] windowId Operand window.
+ *
+ * @retval TRUE Success.
+ * @retval FALSE Failure.
+ *
+ ******************************************************************************
+ */
+
+Bool
+UnityPlatformStickWindow(UnityPlatform *up, // IN
+ UnityWindowId windowId) // IN
+{
+ return SetWindowStickiness(up, windowId, TRUE);
+}
+
+
+/*
+ ******************************************************************************
+ * UnityPlatformUnstickWindow -- */ /**
+ *
+ * @brief "Unstick" a window from the desktop.
+ *
+ * @param[in] up Platform context.
+ * @param[in] windowId Operand window.
+ *
+ * @retval TRUE Success.
+ * @retval FALSE Failure.
+ *
+ ******************************************************************************
+ */
+
+Bool
+UnityPlatformUnstickWindow(UnityPlatform *up, // IN
+ UnityWindowId windowId) // IN
+{
+ return SetWindowStickiness(up, windowId, FALSE);
+}
+
+
+/*
+ ******************************************************************************
+ * Begin file-scope functions.
+ *
+ */
+
+
+/*
+ ******************************************************************************
+ * GetRelevantWMWindow -- */ /**
+ *
+ * @brief Given a UnityWindowId, return the X11 window relevant to WM operations.
+ *
+ * Starting with a Unity window, look for and return its associated
+ * clientWindow. If there is no clientWindow, then return the top-level window.
+ *
+ * @param[in] up Unity/X11 context.
+ * @param[in] windowId Window search for.
+ * @param[out] wmWindow Set to the relevant X11 window.
+ *
+ * @todo Consider exporting this for use in unityPlatformX11Window.c.
+ *
+ * @retval TRUE Relevant window found and recorded in @a wmWindow.
+ * @retval FALSE Unable to find @a windowId.
+ *
+ ******************************************************************************
+ */
+
+static Bool
+GetRelevantWMWindow(UnityPlatform *up, // IN
+ UnityWindowId windowId, // IN
+ Window *wmWindow) // OUT
+{
+ UnityPlatformWindow *upw;
+
+ ASSERT(up);
+
+ upw = UPWindow_Lookup(up, windowId);
+ if (!upw) {
+ return FALSE;
+ }
+
+ *wmWindow = upw->clientWindow ? upw->clientWindow : upw->toplevelWindow;
+ return TRUE;
+}
+
+
+/*
+ ******************************************************************************
+ * SetWindowStickiness -- */ /**
+ *
+ * @brief Sets or clears a window's sticky state.
+ *
+ * @param[in] up Unity/X11 context.
+ * @param[in] windowId Operand window.
+ * @param[in] wantSticky Set to TRUE to stick a window, FALSE to unstick it.
+ *
+ * @retval TRUE Request successfully sent to X server.
+ * @retval FALSE Request failed.
+ *
+ ******************************************************************************
+ */
+
+static Bool
+SetWindowStickiness(UnityPlatform *up, // IN
+ UnityWindowId windowId, // IN
+ Bool wantSticky) // IN
+{
+ GdkWindow *gdkWindow;
+ Window curWindow;
+
+ ASSERT(up);
+
+ if (!GetRelevantWMWindow(up, windowId, &curWindow)) {
+ Debug("%s: Lookup against window %#x failed.\n", __func__, windowId);
+ return FALSE;
+ }
+
+ gdkWindow = gdk_window_foreign_new(curWindow);
+ if (gdkWindow == NULL) {
+ Debug("%s: Unable to create Gdk window?! (%#x)\n", __func__, windowId);
+ return FALSE;
+ }
+
+ if (wantSticky) {
+ gdk_window_stick(gdkWindow);
+ } else {
+ gdk_window_unstick(gdkWindow);
+ }
+
+ gdk_flush();
+ g_object_unref(G_OBJECT(gdkWindow));
+
+ return TRUE;
+}
+
+
+/*
+ *
+ * End file-scope functions.
+ ******************************************************************************
+ */
upw->wantInputFocus = TRUE;
/*
- * Unfortunately the _NET_WM_STATE messages only work for windows that are already
- * mapped, i.e. not iconified or withdrawn.
+ * Okay, client messages to update _NET_WM_STATE are intended only for
+ * /mapped/ windows. (That's my interpretation considering that wm-spec
+ * only mentions mapped windows, and window managers seem to ignore the
+ * request for minimized windows.)
+ *
+ * Rather than directly mapping the window, we'll instead request that
+ * the window manager activate it. Mapping the window has a negative
+ * consequence of stripping the window of its _NET_WM_STATE and
+ * _NET_WM_DESKTOP properties. This is most visible when unminimizing
+ * a sticky window -- the result is that it would lose its stickiness.
*/
- if (!upw->isHidden) {
- XMapRaised(up->display, upw->clientWindow);
- }
+
+ data[0] = 2;
+ data[1] = UnityPlatformGetServerTime(up);
+ data[2] = 0;
+ UnityPlatformSendClientMessage(up, upw->rootWindow, upw->clientWindow,
+ up->atoms._NET_ACTIVE_WINDOW, 32, 4, data);
data[0] = _NET_WM_STATE_REMOVE;
data[1] = up->atoms._NET_WM_STATE_HIDDEN;
unsigned int index = 0;
Bool retval = FALSE;
+ ResolutionInfoType *resInfo = &resolutionInfo;
+
+ if (!resInfo->initialized) {
+ Debug("%s: FAIL! Request for resolution set but plugin is not initialized\n",
+ __FUNCTION__);
+ return RPCIN_SETRETVALS(data, "Invalid guest state: resolution set not initialized", FALSE);
+ }
+
+ if (!resInfo->canSetResolution) {
+ Debug("%s: FAIL! Request for resolution set but res set is not enabled\n",
+ __FUNCTION__);
+ return RPCIN_SETRETVALS(data, "Invalid guest state: resolution set not enabled", FALSE);
+ }
+
/* parse the width and height */
if (!StrUtil_GetNextUintToken(&width, &index, data->args, " ")) {
goto invalid_arguments;
Bool success = FALSE;
const char *p;
+ ResolutionInfoType *resInfo = &resolutionInfo;
+
+ if (!resInfo->initialized) {
+ Debug("%s: FAIL! Request for topology set but plugin is not initialized\n",
+ __FUNCTION__);
+ RPCIN_SETRETVALS(data, "Invalid guest state: topology set not initialized", FALSE);
+ goto out;
+ }
+
+ if (!resInfo->canSetTopology) {
+ Debug("%s: FAIL! Request for topology set but topology set not enabled\n",
+ __FUNCTION__);
+ RPCIN_SETRETVALS(data, "Invalid guest state: topology set not enabled", FALSE);
+ goto out;
+ }
+
/*
* The argument string will look something like:
* <count> [ , <x> <y> <w> <h> ] * count.