From: VMware, Inc <> Date: Wed, 24 Feb 2010 22:34:37 +0000 (-0800) Subject: Unity/X11: Account for guest-Compiz's window decorations. X-Git-Tag: 2010.02.23-236320~4 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=379e9c801967be054c527170686f6ce5e73dee04;p=thirdparty%2Fopen-vm-tools.git Unity/X11: Account for guest-Compiz's window decorations. Compiz does not reparent windows from the root window, but rather adds its decorations to a completely separate peer window. (Unity/X11 tracks only a client window, indicated by whichever window holds the WM_STATE property, and its top-level (child of the root) window for determining window geometry.) Fortunately it makes use of the _NET_FRAME_EXTENTS property to specify the approximate sizes of the frame around its managed windows. (I say approximate in that this property specifies a single width for each window edge, so that doesn't handle things like rounded corners.) This change adjusts the bridge between Unity/X11 and the window tracker such that the tracker is given a window's coordinates including the frame sections. As mentioned above, the caveat is that the guest always provides single rectangles, breaking the prettiness of rounded corners. This will be addressed some other time. Signed-off-by: Marcelo Vanzin --- diff --git a/open-vm-tools/lib/unity/unityPlatformX11Window.c b/open-vm-tools/lib/unity/unityPlatformX11Window.c index bf2a8e67d..b46748448 100644 --- a/open-vm-tools/lib/unity/unityPlatformX11Window.c +++ b/open-vm-tools/lib/unity/unityPlatformX11Window.c @@ -79,6 +79,8 @@ static void UPWindowSetWindows(UnityPlatform *up, Window clientWindow); static Window UPWindowLookupClientLeader(UnityPlatform *up, UnityPlatformWindow *upw); +static void UPWindowUpdateFrameExtents(UnityPlatform *up, + UnityPlatformWindow *upw); #ifdef VMX86_DEVEL /* @@ -2455,6 +2457,8 @@ UPWindowProcessPropertyEvent(UnityPlatform *up, // IN UPWindowUpdateIcon(up, upw); } else if (eventAtom == up->atoms._NET_WM_DESKTOP) { UPWindowUpdateDesktop(up, upw); + } else if (eventAtom == up->atoms._NET_FRAME_EXTENTS) { + UPWindowUpdateFrameExtents(up, upw); } } @@ -2482,21 +2486,36 @@ UPWindowProcessConfigureEvent(UnityPlatform *up, // IN { if (xevent->xconfigure.window == upw->toplevelWindow) { const int border_width = xevent->xconfigure.border_width; - const int x = xevent->xconfigure.x; - const int y = xevent->xconfigure.y; + int x = xevent->xconfigure.x; + int y = xevent->xconfigure.y; + int xprime; + int yprime; + xprime = x + xevent->xconfigure.width + border_width; + yprime = y + xevent->xconfigure.height + border_width; + x -= border_width; + y -= border_width; + +#ifdef VMX86_DEVEL Debug("Moving window %#lx/%#lx to (%d, %d) +(%d, %d)\n", upw->toplevelWindow, upw->clientWindow, - x - border_width, - y - border_width, - xevent->xconfigure.width + border_width, - xevent->xconfigure.height + border_width); + x, y, xprime - x, yprime - y); +#endif + + /* + * If these are the same, then the window hasn't been reparented by + * the window manager, and its window decorations are accounted for + * by the values of the _NET_FRAME_EXTENTS property. + */ + if (upw->toplevelWindow == upw->clientWindow) { + x -= upw->frameExtents[0]; // left + y -= upw->frameExtents[2]; // top + xprime += upw->frameExtents[1]; // right + yprime += upw->frameExtents[3]; // bottom + } UnityWindowTracker_MoveWindow(up->tracker, upw->toplevelWindow, - x - border_width, - y - border_width, - x + xevent->xconfigure.width + border_width, - y + xevent->xconfigure.height + border_width); + x, y, xprime, yprime); if ((xevent->xconfigure.above != None && !upw->lowerWindow) || (xevent->xconfigure.above == None && upw->lowerWindow) @@ -3541,14 +3560,35 @@ UPWindowPushFullUpdate(UnityPlatform *up, // IN Atom *props; int propCount; int i; + int x, y, xprime, yprime; + int border_width; XGetWindowAttributes(up->display, upw->toplevelWindow, &winAttr); + UPWindowUpdateFrameExtents(up, upw); + + x = winAttr.x; + y = winAttr.y; + border_width = winAttr.border_width; + + xprime = x + winAttr.width + border_width; + yprime = y + winAttr.height + border_width; + x -= border_width; + y -= border_width; + + /* + * If these are the same, then the window hasn't been reparented by + * the window manager, and its window decorations are accounted for + * by the values of the _NET_FRAME_EXTENTS property. + */ + if (upw->toplevelWindow == upw->clientWindow) { + x -= upw->frameExtents[0]; // left + y -= upw->frameExtents[2]; // top + xprime += upw->frameExtents[1]; // right + yprime += upw->frameExtents[3]; // bottom + } - UnityWindowTracker_MoveWindow(up->tracker, (UnityWindowId) upw->toplevelWindow, - winAttr.x - winAttr.border_width, - winAttr.y - winAttr.border_width, - winAttr.x + winAttr.width + winAttr.border_width, - winAttr.y + winAttr.height + winAttr.border_width); + UnityWindowTracker_MoveWindow(up->tracker, upw->toplevelWindow, + x, y, xprime, yprime); #if defined(VM_HAVE_X11_SHAPE_EXT) UPWindowUpdateShape(up, upw); @@ -4036,3 +4076,52 @@ UPWindowLookupClientLeader(UnityPlatform *up, // IN return leaderWindow; } + + +/* + *----------------------------------------------------------------------------- + * + * UPWindowUpdateFrameExtents -- + * + * Lookup and record (cache) the _NET_FRAME_EXTENTS property. + * + * Results: + * If _NET_FRAME_EXTENTS is set, upw->frameExtents may be updated. + * + * Side effects: + * None. + * + *----------------------------------------------------------------------------- + */ + +static void +UPWindowUpdateFrameExtents(UnityPlatform *up, + UnityPlatformWindow *upw) +{ + Atom propertyType; + int propertyFormat = 0; + unsigned long itemsReturned = 0; + unsigned long bytesRemaining; + unsigned char *valueReturned = NULL; + Window w = upw->clientWindow ? upw->clientWindow : upw->toplevelWindow; + + ASSERT(up); + ASSERT(upw); + + if (UnityPlatformWMProtocolSupported(up, UNITY_X11_WM__NET_FRAME_EXTENTS) + && XGetWindowProperty(up->display, w, up->atoms._NET_FRAME_EXTENTS, 0, + 1024, False, XA_CARDINAL, + &propertyType, &propertyFormat, &itemsReturned, + &bytesRemaining, &valueReturned) == Success + && propertyFormat == 32 + && itemsReturned >= 4) { + Atom *atomValue = (Atom *)valueReturned; + + upw->frameExtents[0] = atomValue[0]; + upw->frameExtents[1] = atomValue[1]; + upw->frameExtents[2] = atomValue[2]; + upw->frameExtents[3] = atomValue[3]; + + XFree(valueReturned); + } +} diff --git a/open-vm-tools/lib/unity/unityX11.h b/open-vm-tools/lib/unity/unityX11.h index 52e8ce0ba..bd7a2aef1 100644 --- a/open-vm-tools/lib/unity/unityX11.h +++ b/open-vm-tools/lib/unity/unityX11.h @@ -396,6 +396,11 @@ struct UnityPlatformWindow { * our windows (via a PropertyNotify event), we may act accordingly. */ Bool waitingForWmState; + + /* + * See wm-spec::_NET_FRAME_EXTENTS. + */ + uint32 frameExtents[4]; }; /*