X11 / Xlib: окно всегда сверху - PullRequest
3 голосов
/ 03 декабря 2010

Окно должно оставаться поверх всех остальных окон. Возможно ли это как-то с простым x11 / xlib? Поиск в Google для «Always on top» и «x11» / «xlib» не дал ничего полезного.

Я бы избегал наборов инструментов, таких как GTK +, если бы это было возможно.

Я использую Ubuntu с рабочим столом gnome. В меню окна есть опция «Всегда сверху». Это обеспечивается X-сервером или оконным менеджером? Если второй случай, есть ли общая функция, которая может быть вызвана почти для любого wm? Или как это сделать «универсальным» способом X11?


Редактировать: я реализовал ответ fizzer, теперь имея следующий код:
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;
    // ...
    }
}

Но обработка событий и поднятие почти никогда не выполняются, даже моя маска верна?!

Ответы [ 4 ]

10 голосов
/ 26 апреля 2013
#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 );
  }
5 голосов
/ 03 декабря 2010

Вы не хотите использовать XRaiseWindow (), чтобы попытаться остаться на вершине.Некоторые оконные менеджеры будут полностью игнорировать это.Для тех, кто этого не делает, подумайте, что произойдет, если более чем одно приложение попытается сделать это.Boom!Вот почему оконный менеджер отвечает за наложение окон, а не за приложение.

Способ, которым вы делаете это, заключается в использовании протоколов, определенных в советах расширенного диспетчера окон (EWMH), см .: http://www.freedesktop.org/wiki/Specifications/wm-spec

В частности, здесь вы хотите _NET_WM_STATE_ABOVE, как работает пункт меню «Всегда сверху».

Если вы не используете инструментарий, вам нужно привыкнуть к очистке исходного кода инструментария длявыяснить, как делать вещи.В этом случае вы можете посмотреть на функцию gdk_window_set_keep_above () в бэкэнде X11 GTK +.Это покажет, как использовать подсказку _NET_WM_STATE_ABOVE.

2 голосов
/ 03 декабря 2010

Я написал что-то подобное в Xlib много лет назад.Это несколько строк кода.Когда ваше окно частично закрыто, вы получаете событие VisibilityNotify, а затем вызываете XRaiseWindow.Не упустите случай, когда два ваших окна «всегда сверху» перекрываются.

0 голосов
/ 22 декабря 2010

Используйте фактические кнопки заголовка (например, http://www.actualtools.com/titlebuttons/). Это позволяет всегда держать любые окна сверху, свернуть, сделать прозрачными и т. Д.

...