tags:

views:

25

answers:

2

I'm writing a application that put docks in the right side of the screen, like this:

Image

I can reserve space in the side of the screen by using the _NET_WM_STRUT_PARTIAL, so that the maximized windows won't overlap the docks.

In the image, you can see that there is a top panel. The problem is that the docks will overlap the panel. Is there a way to either find out the size of the panel, or to make a way that the panel will reduce to open space to the docks?

I'm using Xlib, by the way.

+3  A: 

I guess you'd have to track all toplevel windows that appear and whether they have _NET_WM_STRUT_PARTIAL in order to compute the work area yourself, minus your own windows. You could look at libwnck code for how to track all toplevels, and look at how window managers compute the _NET_WORKAREA, to see how to do it. Then redo that work but minus your own struts. One issue with this is that if every panel did it, there'd be an infinite loop with them all working around each other. But you can maybe assume people only have a default desktop panel that doesn't do this, plus yours.

Another option might be to just make your panel's window always the full screen height, but if any window is above you, offset what you draw (and offset event handling) down by a bit. The problem is it's hard to track how windows overlap you. XVisibilityEvent helps a bit but doesn't tell you when the window on top just moves. Also you'd have to be sure not to break if say a fullscreen movie ended up covering the whole panel. I guess with this approach you'd probably still end up scanning all toplevels for panels, just like with the first approach.

Havoc P
A: 

By using the good hint given by Havoc P, I was able to formulate this code, that returns the height of a top docking panel:

#include <X11/Xlib.h>
#include <X11/Xatom.h>
#include <limits.h>
#include <stdlib.h>
#include <stdio.h>

static Display* display;

// looks for the maximum "docking height" of all children of this window
static int top_panel_height(Window window)
{
    int height = 0;     // maximum height
    Window w;
    Window* children;
    unsigned int n_children;

    XQueryTree(display, window, &w, &w, &children, &n_children);

    // looks for each one of the children
    int i;
    for(i=0; i<n_children; i++)
    {
        // this is the property we're looking for
        Atom strut = XInternAtom(display, "_NET_WM_STRUT_PARTIAL", 
                False);
        Atom type_return;
        int actual_type;
        unsigned long nitems, bytes;
        unsigned char* data = NULL;

        // load window attributes (we only want to know about the
        //                         windows where y = 0)
        XWindowAttributes xwa;
        XGetWindowAttributes(display, window, &xwa);

        // load the property _NET_WM_STRUT_PARTIAL
        int s = XGetWindowProperty(display, window, strut, 0, LONG_MAX, 
                False, 
                XA_CARDINAL, &type_return, &actual_type,
                &nitems, &bytes, (unsigned char**)&data);
        if(s == Success)
        {
            Atom *state = (Atom *) data;
            // state[2] contains the "dock height"
            if(xwa.y == 0 && nitems > 0 && state[2])
                if(state[2] > height)
                    height = state[2];
        }

        // recursively, traverse the tree of all children of children
        int children_max_height = top_panel_height(children[i]);
        if(children_max_height > height)
            height = children_max_height;
    }

    return height;
}


int main()
{
    display = XOpenDisplay(NULL);
    Window root = RootWindow(display, DefaultScreen(display));

    printf("%d\n", top_panel_height(root));

    return 0;
}

It might not be pretty, but it works :-)

André Wagner