*/
UnityPlatform *
-UnityPlatformInit(UnityWindowTracker *tracker, // IN
- UnityUpdateChannel *updateChannel, // IN
- int *blockedWnd) // UNUSED
+UnityPlatformInit(UnityWindowTracker *tracker, // IN
+ UnityUpdateChannel *updateChannel, // IN
+ int *blockedWnd, // IN, not used
+ DesktopSwitchCallbackManager *desktopSwitchCallbackMgr) // IN, not used
{
UnityPlatform *up;
char *displayName;
UnityWindowId *windows, // IN: array of window ids
unsigned int windowCount) // IN: # of windows in the array
{
- UnityPlatformWindow *upw;
- Atom data[5] = {0,0,0,0,0};
- XWindowChanges winch;
Window sibling = None;
int i;
/*
* Restack everything bottom to top.
*/
- data[0] = 2; // Magic source indicator to give full control
- winch.stack_mode = data[2] = Above; // First window will go at the top of everything
for (i = 0; i < windowCount; i++) {
- unsigned int valueMask = CWStackMode;
+ UnityPlatformWindow *upw;
Window curWindow;
+ Atom data[5] = {0,0,0,0,0};
upw = UPWindow_Lookup(up, windows[i]);
if (!upw) {
curWindow = upw->clientWindow ? upw->clientWindow : upw->toplevelWindow;
UPWindow_SetUserTime(up, upw);
- winch.sibling = data[1] = sibling;
-
- if (sibling != None) {
- valueMask |= CWSibling;
- }
-
if (UnityPlatformWMProtocolSupported(up, UNITY_X11_WM__NET_RESTACK_WINDOW)) {
+ data[0] = 2; // Magic source indicator to give full control
+ data[1] = sibling;
+ data[2] = Above;
+
UnityPlatformSendClientMessage(up, up->rootWindows->windows[0],
curWindow,
up->atoms._NET_RESTACK_WINDOW,
32, 5, data);
} else {
- XReconfigureWMWindow(up->display,
- curWindow,
- 0, valueMask, &winch);
+ XWindowChanges winch = {
+ .stack_mode = Above,
+ .sibling = sibling
+ };
+ unsigned int valueMask = CWStackMode;
+
+ if (sibling != None) {
+ valueMask |= CWSibling;
+ }
+
+ /*
+ * As of writing, Metacity doesn't support _NET_RESTACK_WINDOW and
+ * will block our attempt to raise a window unless it's active, so
+ * we activate the window first.
+ */
+ if (UnityPlatformWMProtocolSupported(up, UNITY_X11_WM__NET_ACTIVE_WINDOW)) {
+ data[0] = 2; // Magic source indicator to give full control
+ data[1] = UnityPlatformGetServerTime(up);
+ data[2] = None;
+ UnityPlatformSendClientMessage(up, up->rootWindows->windows[0],
+ curWindow,
+ up->atoms._NET_ACTIVE_WINDOW,
+ 32, 5, data);
+ }
+
+ XReconfigureWMWindow(up->display, upw->toplevelWindow, 0, valueMask, &winch);
}
- sibling = curWindow;
+ sibling = upw->toplevelWindow;
}
+ XSync(up->display, False);
+
return TRUE;
}
*
* UnityPlatformSetInitialDesktop --
*
- * Set a desktop specified by the desktop id as the initial state.
+ * Set a desktop specified by the desktop id as the initial state.
*
* Results:
* Returns TRUE if successful, and FALSE otherwise.
{
ASSERT(up);
+ /*
+ * Update the uwt with the new active desktop info.
+ */
+
+ UnityWindowTracker_ChangeActiveDesktop(up->tracker, desktopId);
+
if (desktopId >= up->desktopInfo.numDesktops) {
return FALSE;
}
#include "xdrutil.h"
#include "vmware/guestrpc/tclodefs.h"
+/*
+ * The maximum number of capabilities we can set.
+ *
+ * See ResolutionSetCapabilities().
+ */
+#define RESOLUTION_SET_CAPABILITIES_MAX 5
+
/*
* Internal global variables
*/
+/**
+ * The name of the RPC channel we're using, e.g. TOOLS_DAEMON_NAME. Used by
+ * ResolutionSet_SetServerCapability() to determine which capability to set.
+ */
+static const char *rpcChannelName = NULL;
+
/**
* Describes current state of the library.
*/
static Bool ResolutionResolutionSetCB(RpcInData *data);
static Bool ResolutionDisplayTopologySetCB(RpcInData *data);
+static void ResolutionSetServerCapability(unsigned int value);
#if defined(RESOLUTION_WIN32)
static Bool ResolutionDisplayTopologyModesSetCB(RpcInData *data);
static Bool ResolutionChangeHost3DAvailabilityHintCB(RpcInData *data);
-void ResolutionSetSessionChangeCB(gpointer src, ToolsAppCtx *ctx, DWORD code, DWORD sessionID);
#endif
/*
}
-#if defined(RESOLUTION_WIN32)
-/**
- *
- * Handle WTS session state changes sent from Win32 SCM.
- *
- * @param[in] src unused src object
- * @param[in] ctx unused tools app context
- * @param[in] code state change code
- * @param[in] session ID
- */
-
-static void
-ResolutionSetSessionChangeCB(gpointer src,
- ToolsAppCtx *ctx,
- DWORD code,
- DWORD sessionID)
-{
- Debug("%s: enter code %d sessionID %d\n", __FUNCTION__, code, sessionID);
- ResolutionSetSessionChange(code, sessionID);
-}
-#endif
-
-
/**
*
* Handler for TCLO 'Resolution_Set'.
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;
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.
/**
- * Sends the resolution_server capability to the VMX.
+ * Sends the tools.capability.resolution_server RPC to the VMX.
*
- * @param[in] src The source object.
- * @param[in] ctx The app context.
- * @param[in] plugin Plugin registration data.
- * @param[in] set Whether setting or unsetting the capability.
- *
- * @return NULL. The function sends the capability directly.
+ * @param[in] value The value to send for the capability bit.
*/
-
-static void
-ResolutionServerCapReg(ToolsAppCtx *ctx,
- gint set)
+void
+ResolutionSetServerCapability(unsigned int value)
{
- gchar *msg;
- const char *appName = NULL;
-
- if (strcmp(ctx->name, VMTOOLS_GUEST_SERVICE) == 0) {
- appName = TOOLS_DAEMON_NAME;
- } else if (strcmp(ctx->name, VMTOOLS_USER_SERVICE) == 0) {
- appName = TOOLS_DND_NAME;
- } else {
- NOT_REACHED();
+ if (!rpcChannelName) {
+ g_debug("Channel name is null, RPC not sent.\n");
+ return;
}
- msg = g_strdup_printf("tools.capability.resolution_server %s %d",
- appName,
- set);
-
- if (ctx->rpc && !RpcChannel_Send(ctx->rpc, msg, strlen(msg) + 1, NULL, NULL)) {
- g_warning("Setting resolution_server capability failed!\n");
+ if (!RpcOut_sendOne(NULL,
+ NULL,
+ "tools.capability.resolution_server %s %d",
+ rpcChannelName,
+ value)) {
+ g_warning("%s: Unable to set tools.capability.resolution_server\n",
+ __FUNCTION__);
}
-
- g_free(msg);
}
gboolean set,
gpointer data)
{
- enum {
- RES_SET_IDX = 0,
- DPY_TOPO_SET_IDX = 1,
- DPY_GLOBAL_OFFSET_IDX = 2,
- DPY_TOPO_MODES_SET_IDX = 3,
- CHANGE_3D_HINT_IDX = 4
- };
+ /* The array of capabilities to return to the tools service. */
+ ToolsAppCapability capabilityArray[RESOLUTION_SET_CAPABILITIES_MAX];
- ToolsAppCapability caps[] = {
- { TOOLS_CAP_OLD, "resolution_set", 0, 0 },
- { TOOLS_CAP_OLD, "display_topology_set", 0, 0 },
- { TOOLS_CAP_OLD, "display_global_offset", 0, 0 },
- { TOOLS_CAP_NEW, NULL, CAP_SET_TOPO_MODES, 0 },
- { TOOLS_CAP_NEW, NULL, CAP_CHANGE_HOST_3D_AVAILABILITY_HINT, 0},
- };
+ /* The next unused entry in the capabilities array. */
+ unsigned int capabilityCount = 0;
ResolutionInfoType *resInfo = &resolutionInfo;
- int resServerCap = 0;
-Debug("%s: enter\n", __FUNCTION__);
- if (set) {
- if (!resInfo->initialized) {
- return FALSE;
- }
+ Debug("%s: enter\n", __FUNCTION__);
- if (resInfo->canSetResolution) {
- caps[RES_SET_IDX].value = 1;
- resServerCap = 1;
- }
+ if (!resInfo->initialized) {
+ return FALSE;
+ }
- if (resInfo->canSetTopology) {
+ /*
+ * If we can set the guest resolution, add the resolution_set capability to
+ * our array.
+ */
+ if (resInfo->canSetResolution) {
+ capabilityArray[capabilityCount].type = TOOLS_CAP_OLD;
+ capabilityArray[capabilityCount].name = "resolution_set";
+ capabilityArray[capabilityCount].index = 0;
+ capabilityArray[capabilityCount].value = set ? 1 : 0;
+ capabilityCount++;
+
+ /*
+ * Send the resolution_server RPC to the VMX.
+ *
+ * XXX: We need to send this ourselves, instead of including it in the
+ * capability array, because the resolution_server RPC includes the
+ * name of the RPC channel that the VMX should use when sending
+ * resolution set RPCs as an argument.
+ */
+ ResolutionSetServerCapability(set ? 1 : 0);
+ }
- caps[DPY_TOPO_SET_IDX].value = 2;
- caps[DPY_GLOBAL_OFFSET_IDX].value = 1;
-#if defined(RESOLUTION_WIN32)
-Debug("%s: setting DPY_TOPO_MODES_SET_IDX to 1\n", __FUNCTION__);
- caps[DPY_TOPO_MODES_SET_IDX].value = 1;
-#endif
- }
+ /*
+ * If we can set the guest topology, add the display_topology_set and
+ * display_global_offset capabilities to our array.
+ */
+ if (resInfo->canSetTopology) {
+ /*
+ * XXX: We use a value of '2' here because, for historical reasons, the
+ * Workstation/Fusion UI will treat a value of 1 for this capability
+ * as unsupported. See bug 149541.
+ */
+ capabilityArray[capabilityCount].type = TOOLS_CAP_OLD;
+ capabilityArray[capabilityCount].name = "display_topology_set";
+ capabilityArray[capabilityCount].index = 0;
+ capabilityArray[capabilityCount].value = set ? 2 : 0;
+ capabilityCount++;
+
+ capabilityArray[capabilityCount].type = TOOLS_CAP_OLD;
+ capabilityArray[capabilityCount].name = "display_global_offset";
+ capabilityArray[capabilityCount].index = 0;
+ capabilityArray[capabilityCount].value = set ? 1 : 0;
+ capabilityCount++;
}
#if defined(RESOLUTION_WIN32)
- caps[CHANGE_3D_HINT_IDX].value = 1;
+ /*
+ * XXX: I believe we can always handle these RPCs from the service, even on
+ * Vista, so we always set the capabilities here, regardless of the
+ * value of resInfo->canSetTopology.
+ */
+ Debug("%s: setting DPY_TOPO_MODES_SET_IDX to %u\n", __FUNCTION__,
+ set ? 1 : 0);
+
+ capabilityArray[capabilityCount].type = TOOLS_CAP_NEW;
+ capabilityArray[capabilityCount].name = NULL;
+ capabilityArray[capabilityCount].index = CAP_SET_TOPO_MODES;
+ capabilityArray[capabilityCount].value = set ? 1 : 0;
+ capabilityCount++;
+
+ capabilityArray[capabilityCount].type = TOOLS_CAP_NEW;
+ capabilityArray[capabilityCount].name = NULL;
+ capabilityArray[capabilityCount].index = CAP_CHANGE_HOST_3D_AVAILABILITY_HINT;
+ capabilityArray[capabilityCount].value = set ? 1 : 0;
+ capabilityCount++;
#endif
- ResolutionServerCapReg(ctx, resServerCap);
- return VMTools_WrapArray(caps, sizeof *caps, ARRAYSIZE(caps));
+ ASSERT(capabilityCount <= RESOLUTION_SET_CAPABILITIES_MAX);
+
+ return VMTools_WrapArray(capabilityArray,
+ sizeof *capabilityArray,
+ capabilityCount);
}
TOOLS_MODULE_EXPORT ToolsPluginData *
ToolsOnLoad(ToolsAppCtx *ctx)
{
+ RpcChannelCallback rpcs[] = {
+ { "Resolution_Set", &ResolutionResolutionSetCB },
+ { "DisplayTopology_Set", &ResolutionDisplayTopologySetCB },
+#if defined(RESOLUTION_WIN32)
+ { "DisplayTopologyModes_Set", &ResolutionDisplayTopologyModesSetCB },
+ { "ChangeHost3DAvailabilityHint", &ResolutionChangeHost3DAvailabilityHintCB }
+#endif
+ };
+
InitHandle handle;
static ToolsPluginData regData = {
ToolsPluginSignalCb sigs[] = {
{ TOOLS_CORE_SIG_CAPABILITIES, ResolutionSetCapabilities, ®Data },
-#if defined(RESOLUTION_WIN32)
- { TOOLS_CORE_SIG_SESSION_CHANGE, ResolutionSetSessionChangeCB, ®Data },
-#endif
{ TOOLS_CORE_SIG_SHUTDOWN, ResolutionSetShutdown, ®Data }
};
+
ToolsAppReg regs[] = {
{ TOOLS_APP_GUESTRPC, NULL },
{ TOOLS_APP_SIGNALS, VMTools_WrapArray(sigs, sizeof *sigs, ARRAYSIZE(sigs)) }
ResolutionInfoType *resInfo = &resolutionInfo;
+ /*
+ * Save the RPC channel name from the ToolsAppCtx so that we can use it later
+ * in calls to ResolutionSetServerCapability().
+ */
+ if (strcmp(ctx->name, VMTOOLS_GUEST_SERVICE) == 0) {
+ rpcChannelName = TOOLS_DAEMON_NAME;
+ } else if (strcmp(ctx->name, VMTOOLS_USER_SERVICE) == 0) {
+ rpcChannelName = TOOLS_DND_NAME;
+ } else {
+ NOT_REACHED();
+ }
+
resInfo->initialized = FALSE;
/*
ResolutionInit(handle);
- /*
- * Add one or both of the callbacks based on capabilities.
- */
- if (resInfo->canSetResolution || resInfo->canSetTopology) {
- int index = 0;
- RpcChannelCallback rpcs[4];
-
- memset(rpcs, '\0', sizeof rpcs);
-
- if (resInfo->canSetResolution) {
- rpcs[index].name = "Resolution_Set";
- rpcs[index].callback = ResolutionResolutionSetCB;
- index++;
- }
-
- if (resInfo->canSetTopology) {
- rpcs[index].name = "DisplayTopology_Set";
- rpcs[index].callback = ResolutionDisplayTopologySetCB;
- index++;
-#if defined(RESOLUTION_WIN32)
- rpcs[index].name = "DisplayTopologyModes_Set";
- rpcs[index].callback = ResolutionDisplayTopologyModesSetCB;
- index++;
- rpcs[index].name = "ChangeHost3DAvailabilityHint";
- rpcs[index].callback = ResolutionChangeHost3DAvailabilityHintCB;
- index++;
-#endif
- }
-
- regs[0].data = VMTools_WrapArray(rpcs, sizeof *rpcs, index);
- regData.regs = VMTools_WrapArray(regs, sizeof *regs, ARRAYSIZE(regs));
- }
-
-
+ regs[0].data = VMTools_WrapArray(rpcs, sizeof *rpcs, ARRAYSIZE(rpcs));
+ regData.regs = VMTools_WrapArray(regs, sizeof *regs, ARRAYSIZE(regs));
return ®Data;
}