1
/*********************************************************
2
* Copyright (C) 2005 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
* Set of functions to handle guest screen resizing for
23
* vmware-{user,guestd}.
37
#include "resolutionInt.h"
38
#include "resolution.h"
42
* Internal global variables
47
* Describes current state of the library.
49
ResolutionInfoType resolutionInfo = { .initialized = FALSE };
53
* Local function prototypes
56
static Bool ResolutionResolutionSetCB(RpcInData *data);
57
static Bool ResolutionDisplayTopologySetCB(RpcInData *data);
61
* Global function definitions
66
*-----------------------------------------------------------------------------
70
* Initialize the guest resolution library.
73
* TRUE on success, FALSE on failure (bad arguments?).
78
*-----------------------------------------------------------------------------
82
Resolution_Init(const char *tcloChannel,
83
// IN: TCLO channel name; used during capability registration
84
// to tell the VMX whether Resolution_Set is being handled
85
// by VMwareService/guestd or VMwareUser/vmware-user.
87
// IN: Back-end specific handle, if needed. E.g., in the X11
88
// case, this refers to the X11 display handle.
90
// Shorter-named convenience alias. I expect this to be optimized out.
91
ResolutionInfoType *resInfo = &resolutionInfo;
93
ASSERT(resInfo->initialized == FALSE);
94
ASSERT((strcmp(tcloChannel, TOOLS_DAEMON_NAME) == 0) ||
95
(strcmp(tcloChannel, TOOLS_DND_NAME)) == 0);
98
* Blank out the resolutionInfo field, then copy user's arguments.
100
memset(resInfo, 0, sizeof *resInfo);
102
strncpy(resInfo->tcloChannel, tcloChannel, sizeof resInfo->tcloChannel);
103
resInfo->tcloChannel[sizeof resInfo->tcloChannel - 1] = '\0';
105
if (!ResolutionBackendInit(handle)) {
109
resInfo->initialized = TRUE;
116
*-----------------------------------------------------------------------------
118
* Resolution_Cleanup --
120
* Shutdown the library, free resources, etc.
126
* Resolution_* calls will fail until user next calls Resolution_Init().
128
*-----------------------------------------------------------------------------
132
Resolution_Cleanup(void)
134
// Shorter-named convenience alias. I expect this to be optimized out.
135
ResolutionInfoType *resInfo = &resolutionInfo;
137
if (!resInfo->initialized) {
141
Resolution_UnregisterCaps();
142
Resolution_CleanupBackdoor();
143
ResolutionBackendCleanup();
145
ASSERT(!resInfo->cbResolutionRegistered);
146
ASSERT(!resInfo->cbTopologyRegistered);
147
ASSERT(!resInfo->rpcIn);
151
/*-----------------------------------------------------------------------------
153
* Resolution_InitBackdoor --
155
* Register RpcIn callbacks for supported/available RpcIn commands.
161
* Resolution_Set & DisplayTopology_Set callbacks may be registered.
163
*-----------------------------------------------------------------------------
167
Resolution_InitBackdoor(RpcIn *rpcIn)
169
// Shorter-named convenience alias. I expect this to be optimized out.
170
ResolutionInfoType *resInfo = &resolutionInfo;
172
ASSERT(resInfo->initialized);
175
resInfo->rpcIn = rpcIn;
177
if (resInfo->canSetResolution) {
178
RpcIn_RegisterCallbackEx(resInfo->rpcIn, "Resolution_Set",
179
ResolutionResolutionSetCB, NULL);
180
resInfo->cbResolutionRegistered = TRUE;
183
if (resInfo->canSetTopology) {
184
RpcIn_RegisterCallbackEx(resInfo->rpcIn, "DisplayTopology_Set",
185
ResolutionDisplayTopologySetCB, NULL);
186
resInfo->cbTopologyRegistered = TRUE;
192
*-----------------------------------------------------------------------------
194
* Resolution_CleanupBackdoor --
196
* Unregisters RpcIn callbacks.
202
* Resolution callbacks are removed.
204
*-----------------------------------------------------------------------------
208
Resolution_CleanupBackdoor(void)
210
// Shorter-named convenience alias. I expect this to be optimized out.
211
ResolutionInfoType *resInfo = &resolutionInfo;
213
if (!resInfo->initialized || !resInfo->rpcIn) {
217
if (resInfo->cbResolutionRegistered) {
218
RpcIn_UnregisterCallback(resInfo->rpcIn, "Resolution_Set");
219
resInfo->cbResolutionRegistered = FALSE;
222
if (resInfo->cbTopologyRegistered) {
223
RpcIn_UnregisterCallback(resInfo->rpcIn, "DisplayTopology_Set");
224
resInfo->cbTopologyRegistered = FALSE;
227
resInfo->rpcIn = FALSE;
232
*-----------------------------------------------------------------------------
234
* Resolution_RegisterCaps --
236
* Register the "Resolution_Set" capability. Sometimes this needs to
237
* be done separately from the TCLO callback registration, so we
238
* provide it separately here.
247
*-----------------------------------------------------------------------------
251
Resolution_RegisterCaps(void)
253
// Shorter-named convenience alias. I expect this to be optimized out.
254
ResolutionInfoType *resInfo = &resolutionInfo;
256
if (!resInfo->initialized) {
260
if (resInfo->canSetResolution) {
261
if (!RpcOut_sendOne(NULL, NULL, "tools.capability.resolution_set 1")) {
262
Debug("%s: Unable to register resolution set capability\n",
267
if (!RpcOut_sendOne(NULL, NULL, "tools.capability.resolution_server %s 1",
268
resInfo->tcloChannel)) {
269
Debug("%s: Unable to register resolution server capability\n",
273
* Note that we do not return false so that we stay backwards
274
* compatible with old vmx code (Workstation 6/ESX 3.5) that doesn't
275
* handle resolution_server.
280
if (resInfo->canSetTopology) {
281
if (!RpcOut_sendOne(NULL, NULL, "tools.capability.display_topology_set 2")) {
282
Debug("%s: Unable to register topology set capability\n",
286
if (!RpcOut_sendOne(NULL, NULL, "tools.capability.display_global_offset 1")) {
287
Debug("%s: Unable to register topology global offset capability\n",
290
* Ignore failures - host may not support these RPCs.
302
*-----------------------------------------------------------------------------
304
* Resolution_UnregisterCaps --
306
* Unregister the "Resolution_Set" and "DisplayTopology_Set" capabilities.
315
*-----------------------------------------------------------------------------
319
Resolution_UnregisterCaps(void)
321
// Shorter-named convenience alias. I expect this to be optimized out.
322
ResolutionInfoType *resInfo = &resolutionInfo;
325
* RpcIn doesn't have an unregister facility, so all we need to do
326
* here is unregister the capability.
329
if (!RpcOut_sendOne(NULL, NULL, "tools.capability.resolution_set 0")) {
330
Debug("%s: Unable to unregister ResolutionSet capability\n",
335
if (!RpcOut_sendOne(NULL, NULL, "tools.capability.resolution_server %s 0",
336
resInfo->tcloChannel)) {
337
Debug("%s: Unable to unregister resolution server capability\n",
341
* Don't return false here so that an older vmx (Workstation 6/ESX 3.5)
342
* that that supports resolution_set and not resolution_server will
347
if (!RpcOut_sendOne(NULL, NULL, "tools.capability.display_topology_set 0") ||
348
!RpcOut_sendOne(NULL, NULL, "tools.capability.display_global_offset 0")) {
349
Debug("%s: Unable to unregister TopologySet capability\n",
352
* Ignore failures - host may not support these RPCs.
361
* Local function definitions
366
*-----------------------------------------------------------------------------
368
* ResolutionResolutionSetCB --
370
* Handler for TCLO 'Resolution_Set'.
373
* TRUE if we can reply, FALSE otherwise.
378
*-----------------------------------------------------------------------------
382
ResolutionResolutionSetCB(RpcInData *data) // IN/OUT:
386
unsigned int index = 0;
389
/* parse the width and height */
390
if (!StrUtil_GetNextUintToken(&width, &index, data->args, " ")) {
391
goto invalid_arguments;
393
if (!StrUtil_GetNextUintToken(&height, &index, data->args, "")) {
394
goto invalid_arguments;
397
retval = ResolutionSetResolution(width, height);
400
return RPCIN_SETRETVALS(data, retval ? "" : "Invalid arguments", retval);
405
*-----------------------------------------------------------------------------
407
* ResolutionDisplayTopologySetCB --
409
* Handler for TCLO 'DisplayTopology_Set'.
411
* Routine unmarshals RPC arguments and passes over to back-end
415
* TRUE if we can reply, FALSE otherwise.
420
*-----------------------------------------------------------------------------
424
ResolutionDisplayTopologySetCB(RpcInData *data) // IN/OUT:
426
DisplayTopologyInfo *displays = NULL;
427
unsigned int count, i;
428
Bool success = FALSE;
432
* The argument string will look something like:
433
* <count> [ , <x> <y> <w> <h> ] * count.
436
* 3 , 0 0 640 480 , 640 0 800 600 , 0 480 640 480
439
if (sscanf(data->args, "%u", &count) != 1) {
440
return RPCIN_SETRETVALS(data,
441
"Invalid arguments. Expected \"count\"",
447
displays = malloc(sizeof *displays * count);
449
RPCIN_SETRETVALS(data,
450
"Failed to alloc buffer for display info",
455
for (p = data->args, i = 0; i < count; i++) {
458
RPCIN_SETRETVALS(data,
459
"Expected comma separated display list",
463
p++; /* Skip past the , */
465
if (sscanf(p, " %d %d %d %d ", &displays[i].x,
466
&displays[i].y, &displays[i].width, &displays[i].height) != 4) {
467
RPCIN_SETRETVALS(data,
468
"Expected x, y, w, h in display entry",
474
success = ResolutionSetTopology(count, displays);
476
RPCIN_SETRETVALS(data, success ? "" : "ResolutionSetTopology failed", success);