1 #include "x.hpp"
2 
3 using namespace slop;
4 
getWindowGeometry(Window win,bool 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         XFree( data );
64         return glm::vec4( x, y, width, height );
65     } else {
66         // Either the WM is malfunctioning, or the window specified isn't a window manager frame.
67         // so we just rely on X to give a decent geometry.
68         XWindowAttributes attr;
69         XGetWindowAttributes( x11->display, win, &attr );
70         unsigned int width = attr.width;
71         unsigned int height = attr.height;
72         // We combine both border widths.
73         unsigned int border = attr.border_width;
74         int x, y;
75         // Gotta translate them into root coords, we can adjust for the border width here.
76         Window junk;
77         XTranslateCoordinates( x11->display, win, attr.root, -border, -border, &x, &y, &junk );
78         width += border*2;
79         height += border*2;
80         return glm::vec4( x, y, width, height );
81     }
82 }
83 
hasCompositor()84 bool X11::hasCompositor() {
85     std::stringstream prop_name;
86     prop_name << "_NET_WM_CM_S" << XScreenNumberOfScreen( screen );
87     Atom prop_atom = XInternAtom(display, prop_name.str().c_str(), False);
88     return XGetSelectionOwner(display, prop_atom) != None;
89 }
90 
X11(std::string displayName)91 X11::X11( std::string displayName ) {
92     // Initialize display
93     display = XOpenDisplay( displayName.c_str() );
94     if ( !display ) {
95         throw std::runtime_error(std::string("Error: Failed to open X display: ") + displayName );
96     }
97     screen = ScreenOfDisplay( display, DefaultScreen( display ) );
98     visual = DefaultVisual( display, XScreenNumberOfScreen( screen ) );
99     root = DefaultRootWindow( display );
100 }
101 
~X11()102 X11::~X11() {
103     XCloseDisplay( display );
104 }
105