diff options
author | Micah Dowty <micah@vmware.com> | 2009-06-01 10:47:51 -0700 |
---|---|---|
committer | Philip Langdale <philipl@fido2.homeip.net> | 2009-06-01 10:47:51 -0700 |
commit | c2d9678431a40f6a15dc7f50690507cdda8d11e2 (patch) | |
tree | 31286fda5811516c562e841fd4a614b097a56c90 /src/vmwarectrl.c | |
parent | d10841493c4707f23f928d7580bc5bddb51d22a6 (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.c | 50 |
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; } |