Browse Source

fixed border detection on certain window managers (pretty much just mutter).

naelstrof 6 years ago
parent
commit
1f884e211a
1 changed files with 72 additions and 29 deletions
  1. 72
    29
      src/x.cpp

+ 72
- 29
src/x.cpp View File

@@ -2,39 +2,82 @@
2 2
 
3 3
 using namespace slop;
4 4
 
5
-glm::vec4 slop::getWindowGeometry( Window win, bool removeDecoration) {
6
-    XWindowAttributes attr;         
7
-    XGetWindowAttributes( x11->display, win, &attr );
8
-    unsigned int width = attr.width;           
9
-    unsigned int height = attr.height;         
10
-    unsigned int border = attr.border_width;   
11
-    int x, y;
12
-    Window junk;
13
-    XTranslateCoordinates( x11->display, win, attr.root, -attr.border_width, -attr.border_width, &x, &y, &junk );
14
-    if ( !removeDecoration ) {
5
+glm::vec4 slop::getWindowGeometry( Window win, bool removeDecoration ) {
6
+    // First lets check for if we're a window manager frame.
7
+    Window root, parent;
8
+    Window* children;
9
+    unsigned int num_children;
10
+    XQueryTree( x11->display, win, &root, &parent, &children, &num_children);
11
+
12
+    // To do that, we check if our top level child happens to have the _NET_FRAME_EXTENTS atom.
13
+    unsigned char *data;
14
+    Atom type_return;
15
+    unsigned long nitems_return;
16
+    unsigned long bytes_after_return;
17
+    int format_return;
18
+    bool window_frame = false;
19
+    Window actualWindow = win;
20
+    if ( num_children > 0 && XGetWindowProperty( x11->display, children[num_children-1], XInternAtom( x11->display, "_NET_FRAME_EXTENTS", False),
21
+                        0, LONG_MAX, False, XA_CARDINAL, &type_return,
22
+                        &format_return, &nitems_return, &bytes_after_return,
23
+                        &data) == Success ) {
24
+        if ((type_return == XA_CARDINAL) && (format_return == 32) && (nitems_return == 4) && (data)) {
25
+            actualWindow = children[num_children-1];
26
+            window_frame = true;
27
+        }
28
+    }
29
+
30
+    // If we actually don't want the window frame (decoration), we just actually grab the decoration's innards.
31
+    // And ignore all of the _NET_FRAME_EXTENTS information.
32
+    if ( actualWindow != win && removeDecoration ) {
33
+        win = actualWindow;
34
+        window_frame = false;
35
+    }
36
+
37
+    // If we're a window frame, we actually get the dimensions of the child window, then add the _NET_FRAME_EXTENTS to it.
38
+    // (then add the border width of the window frame after that.)
39
+    if ( window_frame ) {
40
+        // First lets grab the border width.
41
+        XWindowAttributes frameattr;
42
+        XGetWindowAttributes( x11->display, win, &frameattr );
43
+        // Then lets grab the dims of the child window.
44
+        XWindowAttributes attr;
45
+        XGetWindowAttributes( x11->display, actualWindow, &attr );
46
+        unsigned int width = attr.width;           
47
+        unsigned int height = attr.height;         
48
+        // We combine both border widths.
49
+        unsigned int border = attr.border_width+frameattr.border_width;   
50
+        int x, y;
51
+        // Gotta translate them into root coords, we can adjust for the border width here.
52
+        Window junk;
53
+        XTranslateCoordinates( x11->display, actualWindow, attr.root, -border, -border, &x, &y, &junk );
54
+        width += border*2;
55
+        height += border*2;
56
+        // Now uh, remember that _NET_FRAME_EXTENTS stuff? That's the window frame information.
57
+        // We HAVE to do this because mutter likes to mess with window sizes with shadows and stuff.
58
+        unsigned long* ldata = (unsigned long*)data;
59
+        width += ldata[0] + ldata[1];
60
+        height += ldata[2] + ldata[3];
61
+        x -= ldata[0];
62
+        y -= ldata[2];
63
+        return glm::vec4( x, y, width, height );
64
+    } else {
65
+        // Either the WM is malfunctioning, or the window specified isn't a window manager frame.
66
+        // so we just rely on X to give a decent geometry.
67
+        XWindowAttributes attr;
68
+        XGetWindowAttributes( x11->display, win, &attr );
69
+        unsigned int width = attr.width;           
70
+        unsigned int height = attr.height;         
71
+        // We combine both border widths.
72
+        unsigned int border = attr.border_width;   
73
+        int x, y;
74
+        // Gotta translate them into root coords, we can adjust for the border width here.
75
+        Window junk;
76
+        XTranslateCoordinates( x11->display, win, attr.root, -border, -border, &x, &y, &junk );
15 77
         width += border*2;
16 78
         height += border*2;
17 79
         return glm::vec4( x, y, width, height );
18 80
     }
19
-    // This is required to be defined by the window manager, so we can assume it exists.
20
-    Atom actual_type;
21
-    int actual_format;
22
-    unsigned long nitems, bytes_after;
23
-    unsigned char *data;
24
-    int result = XGetWindowProperty(x11->display, win,
25
-                                    XInternAtom(x11->display, "_NET_FRAME_EXTENTS", true),
26
-                                    0, 4, False, AnyPropertyType, 
27
-                                    &actual_type, &actual_format, &nitems, &bytes_after, &data);
28
-    if ( result == Success ) {
29
-        // Make sure we got the data we expect...
30
-        if ((nitems == 4) && (bytes_after == 0)) {
31
-            x += (int)data[0];
32
-            width -= (int)data[1];
33
-            y += (int)data[2];
34
-            height -= (int)data[3];
35
-        }
36
-    }
37
-    return glm::vec4( x, y, width, height );
38 81
 }
39 82
 
40 83
 bool X11::hasCompositor() {