]> git.ipfire.org Git - thirdparty/open-vm-tools.git/commitdiff
Unity/X11: Account for guest-Compiz's window decorations.
authorVMware, Inc <>
Wed, 24 Feb 2010 22:34:37 +0000 (14:34 -0800)
committerMarcelo Vanzin <mvanzin@vmware.com>
Wed, 24 Feb 2010 22:34:37 +0000 (14:34 -0800)
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 <mvanzin@vmware.com>
open-vm-tools/lib/unity/unityPlatformX11Window.c
open-vm-tools/lib/unity/unityX11.h

index bf2a8e67df127d260357d3202e0bf30691b93576..b46748448d2d143e3ec88c22d353be5ecfa737dc 100644 (file)
@@ -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);
+   }
+}
index 52e8ce0ba7c8cff87f10cdcd5039f067adff6714..bd7a2aef10db66adba86d9413983da44d795da7a 100644 (file)
@@ -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];
 };
 
 /*