2010-10-23 31 views
1

J'écris une application qui a mis les quais dans le côté droit de l'écran, comme celui-ci:Découvrez la taille d'un panneau avec Xlib

Image

je peux réserver un espace dans le côté de l'écran en utilisant le _NET_WM_STRUT_PARTIAL, de sorte que les fenêtres agrandies ne chevauchent pas les quais.

Dans l'image, vous pouvez voir qu'il y a un panneau supérieur. Le problème est que les docks chevaucheront le panneau. Y a-t-il un moyen de déterminer la taille du panneau ou de faire en sorte que le panneau réduise pour ouvrir l'espace aux docks? J'utilise Xlib, au fait.

Répondre

0

En utilisant la bonne indication donnée par Havoc P, j'ai pu formuler ce code, qui retourne la hauteur d'un panneau d'accueil haut:

#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; 
} 

Il pourrait ne pas être assez, mais ça fonctionne :-)

3

Je suppose que vous devrez suivre toutes les fenêtres de niveau supérieur qui apparaissent et si elles ont _NET_WM_STRUT_PARTIAL afin de calculer la zone de travail vous-même, moins vos propres fenêtres. Vous pouvez regarder le code libwnck pour savoir comment faire le suivi de tous les niveaux, et regarder comment les gestionnaires de fenêtres calculent le _NET_WORKAREA, pour voir comment le faire. Puis refaites ce travail mais sans vos propres entretoises. Un problème avec ceci est que si chaque panneau le faisait, il y aurait une boucle infinie avec eux tous travaillant les uns avec les autres. Mais vous pouvez supposer que les gens n'ont qu'un panneau de bureau par défaut qui ne le fait pas, plus le vôtre. Une autre option pourrait être de faire en sorte que la fenêtre de votre panneau soit toujours la hauteur de l'écran, mais si une fenêtre est au-dessus de vous, décalez d'un peu ce que vous dessinez (et désactivez la gestion des événements). Le problème est qu'il est difficile de savoir comment les fenêtres se chevauchent. XVisibilityEvent aide un peu mais ne vous dit pas quand la fenêtre du dessus bouge juste. Aussi, vous devez être sûr de ne pas casser si un film en plein écran finit par couvrir tout le panel. Je suppose qu'avec cette approche, vous finirez probablement par scanner tous les niveaux pour les panneaux, comme avec la première approche.