summaryrefslogtreecommitdiff
path: root/src/vmwarectrl.c
diff options
context:
space:
mode:
authorMicah Dowty <micah@vmware.com>2009-06-01 10:47:51 -0700
committerPhilip Langdale <philipl@fido2.homeip.net>2009-06-01 10:47:51 -0700
commitc2d9678431a40f6a15dc7f50690507cdda8d11e2 (patch)
tree31286fda5811516c562e841fd4a614b097a56c90 /src/vmwarectrl.c
parentd10841493c4707f23f928d7580bc5bddb51d22a6 (diff)
An imperfect fix for Xinerama state changes without a mode change
This patch improves behaviour for Xinerama state changes (via the VMWARE_CTRL) extension that don't have an accompanying mode change. This will be the case if a new Xinerama monitor layout has a bounding box with an identical size to that of the previous layout. Prior to this patch, the behaviour was pretty bad. If you sent two Xinerama states with the same bounding box, the second state would be set as pending but no actual mode change would occur, because the X server would already be in the right video mode. This means that the pending mode stays pending. If another Xinerama state comes in after this, we would hit our "Aborting due to existing pending state" error, and the new state would be discarded. This means we'd drop the mode switch on the floor, plus we'd lie to the client and say it worked. One example of the user-visible symptoms from this: The user has four monitors of the same size. We'll call them A through D. The VM goes into full-screen mode, and they set it to use screens ABC. Now they switch to BCD. These have the same bounding box size, so no mode change occurs and a topology is still pending. Now they switch to monitors BC. This mode switch is dropped, so the guest is still in the ABC topology and the mode is too wide for BC. This patch is an incomplete fix. If we're setting a new topology with the same bounding box, we'll flush the Xinerama state immediately since we know the mode switch will never occur. This means we don't get stuck with xineramaNextState set when it shouldn't be, and we don't have the problem with dropping subsequent mode changes. We also do set the new Xinerama state, so apps that query it will see the updated state immediately. But the fix isn't perfect- as far as I can tell, there's no way to notify applications that the monitor layout changed without a mode switch. So even though we've set the new topology, most apps won't notice. There are ways we could hack around this, but none of them are pretty.
Diffstat (limited to 'src/vmwarectrl.c')
-rw-r--r--src/vmwarectrl.c50
1 files changed, 49 insertions, 1 deletions
diff --git a/src/vmwarectrl.c b/src/vmwarectrl.c
index 634b9ca..d9ceaa4 100644
--- a/src/vmwarectrl.c
+++ b/src/vmwarectrl.c
@@ -282,11 +282,59 @@ VMwareCtrlDoSetTopology(ScrnInfoPtr pScrn,
if (xineramaState) {
memcpy(xineramaState, extents, number * sizeof (VMWAREXineramaRec));
+ /*
+ * Make this the new pending Xinerama state. Normally we'll
+ * wait until the next mode switch in order to synchronously
+ * push this state out to X clients and the virtual hardware.
+ *
+ * However, if we're already in the right video mode, there
+ * will be no mode change. In this case, push it out
+ * immediately.
+ */
xfree(pVMWARE->xineramaNextState);
pVMWARE->xineramaNextState = xineramaState;
pVMWARE->xineramaNextNumOutputs = number;
- return VMwareCtrlDoSetRes(pScrn, maxX, maxY, FALSE);
+ if (maxX == pVMWARE->ModeReg.svga_reg_width &&
+ maxY == pVMWARE->ModeReg.svga_reg_height) {
+
+ /*
+ * XXX:
+ *
+ * There are problems with trying to set a Xinerama state
+ * without a mode switch. The biggest one is that
+ * applications typically won't notice a topology change
+ * that occurs without a mode switch. If you run "xdpyinfo
+ * -ext XINERAMA" after one such topology change, it will
+ * report the new data, but apps (like the GNOME Panel)
+ * will not notice until the next mode change.
+ *
+ * I don't think there's any good solution to this... as
+ * far as I know, even on a non-virtualized machine
+ * there's no way for an app to find out if the Xinerama
+ * opology changes without a resolution change also
+ * occurring. There might be some cheats we can take, like
+ * swithcing to a new mode with the same resolution and a
+ * different (fake) refresh rate, or temporarily switching
+ * to an intermediate mode. Ick.
+ *
+ * The other annoyance here is that when we reprogram the
+ * SVGA device's monitor topology registers, it may
+ * rearrange those monitors on the host's screen, but they
+ * will still have the old contents. This might be
+ * correct, but it isn't guaranteed to match what's on X's
+ * framebuffer at the moment. So we'll send a
+ * full-framebuffer update rect afterwards.
+ */
+
+ vmwareNextXineramaState(pVMWARE);
+ vmwareSendSVGACmdUpdateFullScreen(pVMWARE);
+
+ return TRUE;
+ } else {
+ return VMwareCtrlDoSetRes(pScrn, maxX, maxY, FALSE);
+ }
+
} else {
return FALSE;
}