2010-12-03 4 views
3

Окно должно оставаться поверх всех остальных окон. Возможно ли это с помощью простого x11/xlib? Googling для «Always on top» и «x11»/«xlib» не принес ничего полезного.X11/Xlib: Окно всегда сверху

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

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


Edit: я реализовал ответ 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; 
    // ... 
    } 
} 

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

+0

Практически все оконный инструментарий низкого уровня определяется в одном или обоих этих языках, так что если это может быть сделано, то это можно сделать в C/C++. Это не вопрос языка. – 2010-12-03 11:58:54

+0

изменил вопрос. конечно, это не о том, возможно ли это с помощью c/C++, но если это было возможно, используя минимальную привязку ** x11/xlib ** только – Atmocreations 2010-12-03 12:05:47

+0

Получаете ли вы другие типы событий? – fizzer 2010-12-03 13:26:32

ответ

5

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

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

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

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

2

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

-6

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

10
#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); 
    } 
Смежные вопросы