Question

Une fenêtre devrait rester au-dessus de toutes les autres fenêtres. Est-ce possible avec une certaine façon x11 / xlib plaine? Googler « Toujours au-dessus » et « x11 » / « xlib » n'a retourné quelque chose d'utile.

Il faut éviter des boîtes à outils comme GTK +, si possible, en quelque sorte.

J'utilise Ubuntu avec bureau GNOME. Dans le menu de la fenêtre, il y a une option "Always On Top". Est-ce fourni par le serveur X ou le gestionnaire de fenêtres? Si le second est le cas, est-il une fonction générale qui peut être appelée pour presque tous les wm? Ou comment faire d'une manière « X11-générique »?


Edit: Je mis en œuvre la réponse de fizzer, ayant maintenant le code suivant:

XSelectInput(this->display, this->window,
    ButtonPressMask |
    StructureNotifyMask |
    ExposureMask |
    KeyPressMask |
    PropertyChangeMask |
    VisibilityChangeMask ); 
// ...
// In a loop:
if (XPending(this->display) >= 0)
{
    XNextEvent(this->display, &ev);
    switch(ev.type) {
    // ...
    case VisibilityNotify:
        XRaiseWindow(this->display, this->window);
        XFlush(this->display);
    break;
    // ...
    }
}

Mais le eventhandling et presque jamais Raising est exécuté même mon masque est correct?

Était-ce utile?

La solution

Vous ne voulez pas utiliser XRaiseWindow () pour essayer de rester au-dessus. Certains gestionnaires de fenêtres ignorent complètement. Pour ceux qui ne le font pas, pensez à ce qui se passe si plus d'une application essaie de le faire. Boom! Voilà pourquoi le gestionnaire de fenêtres est en charge des fenêtres d'empilage, pas l'application.

La façon dont vous le faire est d'utiliser les protocoles définis dans les Conseils du gestionnaire de fenêtres étendues (EWMH), voir: http://www.freedesktop.org/wiki/Specifications/wm-spec

Plus précisément ici que vous voulez _NET_WM_STATE_ABOVE qui est de savoir comment l'élément de menu « Toujours visible » œuvres.

Si vous n'utilisez pas une boîte à outils que vous aurez envie de vous habituer à balayage dans le code source de boîte à outils pour savoir comment faire les choses. Dans ce cas, vous pouvez regarder la fonction gdk_window_set_keep_above () dans back-end de X11 GTK +. Cela montrera comment utiliser l'indice de _NET_WM_STATE_ABOVE.

Autres conseils

#define _NET_WM_STATE_REMOVE        0    // remove/unset property
#define _NET_WM_STATE_ADD           1    // add/set property
#define _NET_WM_STATE_TOGGLE        2    // toggle property
...
...
Atom wmStateAbove = XInternAtom( display, "_NET_WM_STATE_ABOVE", 1 );
if( wmStateAbove != None ) {
    printf( "_NET_WM_STATE_ABOVE has atom of %ld\n", (long)wmStateAbove );
} else {
    printf( "ERROR: cannot find atom for _NET_WM_STATE_ABOVE !\n" );
}

Atom wmNetWmState = XInternAtom( display, "_NET_WM_STATE", 1 );
if( wmNetWmState != None ) {
    printf( "_NET_WM_STATE has atom of %ld\n", (long)wmNetWmState );
} else {
    printf( "ERROR: cannot find atom for _NET_WM_STATE !\n" );
}
// set window always on top hint
if( wmStateAbove != None ) {
    XClientMessageEvent xclient;
    memset( &xclient, 0, sizeof (xclient) );
    //
    //window  = the respective client window
    //message_type = _NET_WM_STATE
    //format = 32
    //data.l[0] = the action, as listed below
    //data.l[1] = first property to alter
    //data.l[2] = second property to alter
    //data.l[3] = source indication (0-unk,1-normal app,2-pager)
    //other data.l[] elements = 0
    //
    xclient.type = ClientMessage;
    xclient.window = mywin; // GDK_WINDOW_XID(window);
    xclient.message_type = wmNetWmState; //gdk_x11_get_xatom_by_name_for_display( display, "_NET_WM_STATE" );
    xclient.format = 32;
    xclient.data.l[0] = _NET_WM_STATE_ADD; // add ? _NET_WM_STATE_ADD : _NET_WM_STATE_REMOVE;
    xclient.data.l[1] = wmStateAbove; //gdk_x11_atom_to_xatom_for_display (display, state1);
    xclient.data.l[2] = 0; //gdk_x11_atom_to_xatom_for_display (display, state2);
    xclient.data.l[3] = 0;
    xclient.data.l[4] = 0;
    //gdk_wmspec_change_state( FALSE, window,
    //  gdk_atom_intern_static_string ("_NET_WM_STATE_BELOW"),
    //  GDK_NONE );
    XSendEvent( display,
      //mywin - wrong, not app window, send to root window!
      root, // !! DefaultRootWindow( display ) !!!
      False,
      SubstructureRedirectMask | SubstructureNotifyMask,
      (XEvent *)&xclient );
  }

J'ai écrit quelque chose comme ça dans Xlib il y a plusieurs années. Il est quelques lignes de code. Lorsque la fenêtre est partiellement obscurci vous obtenez un événement VisibilityNotify, puis appelez XRaiseWindow. Attention pour le cas où deux de vos fenêtres « toujours au-dessus » se chevauchent.

Utilisez les boutons Titre réels (http://www.actualtools.com/titlebuttons/) par exemple. Il permet de rester toutes les fenêtres toujours sur le dessus, rouler, faire de la transparence et etc ..

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top