Предотвращение перекрытия окон в GTK

У меня есть приложение Python/Linux, которое отображает нужную мне информацию в окне GTK. Для целей данного обсуждения он должен вести себя точно так же, как док-станция — существовать на всех виртуальных рабочих столах, и развернутые окна не перекрывают ее.

Первый пункт довольно прост, но я провел дни, стуча головой о монитор, пытаясь понять второй пункт — предотвращение наложения. Мое приложение не должно закрываться, если развернуто другое окно. Настроить «всегда сверху» недостаточно, так как другие окна просто находятся за моей информационной панелью, а не останавливаются на ее краю.

Вкратце: с окном в стиле док-панели, как вы можете предотвратить максимизацию других окон над ним или под ним?

Обновление: проблема решена благодаря vsemenov


person Josh    schedule 04.10.2010    source источник


Ответы (1)


Используйте _NET_WM_STRUT и _NET_WM_STRUT_PARTIAL (для обратной совместимости) для резервирования места на краю рабочего стола системы X Window.

С помощью PyGtk вы можете установить эти свойства следующим образом, предполагая, что self.window является экземпляром gtk.Window:

self.window.get_toplevel().show() # must call show() before property_change()
self.window.get_toplevel().window.property_change("_NET_WM_STRUT", 
    "CARDINAL", 32, gtk.gdk.PROP_MODE_REPLACE, [0, 0, 0, bottom_width]) 

Пояснение к параметру данных [0, 0, 0, bottom_width] выше:

Этот параметр определяет ширину зарезервированного пространства на каждой границе экрана рабочего стола по порядку: [left, right, top, bottom]. Таким образом, [0, 0, 0, 50] зарезервирует 50 пикселей в нижней части экрана рабочего стола для вашего виджета.

Вот простой рабочий пример:

import gtk

class PyGtkWidgetDockExample:
    def __init__(self):
        self.window = gtk.Window(gtk.WINDOW_TOPLEVEL)
        self.window.set_default_size(100, gtk.gdk.screen_height())
        self.window.move(gtk.gdk.screen_width()-100, 0)
        self.window.set_type_hint(gtk.gdk.WINDOW_TYPE_HINT_DOCK)        
        self.window.show()          
        self.window.window.property_change("_NET_WM_STRUT", "CARDINAL", 32, 
            gtk.gdk.PROP_MODE_REPLACE, [0, 100, 0, 0])               

app = PyGtkWidgetDockExample()
gtk.main()
person vls    schedule 04.10.2010
comment
Это огромная помощь, и она проясняет часть кода, который я нашел в PyPanel при попытке решить эту проблему. Я вижу, что документы показывают это как property_change (свойство, тип, формат, режим, данные). Можете ли вы уточнить отправляемые данные? Я получил высоту, вы можете сказать мне о нулях? - person Josh; 05.10.2010
comment
Хм спасибо за ответ. Я использую screen = gtk.gdk.screen_get_default() root = screen.get_root_window() root.property_change(_NET_WM_STRUT, CARDINAL, 32, gtk.gdk.PROP_MODE_REPLACE, [0, 0, 0, 64]) безуспешно. Вы имеете в виду корневое окно, верно? Или окно моего приложения? Мне не везет в любом случае. - person Josh; 05.10.2010
comment
То же самое при изменении свойств окна приложения. Нет ошибок, но нет явного эффекта - person Josh; 05.10.2010
comment
@Josh: вы хотите вызвать property_change в окне верхнего уровня вашего приложения, на которое вы можете ссылаться из любого gtk.Window, используя self.window.get_toplevel().window.property_change(). Если вы пойдете по маршруту gtk.gdk.screen_get_default().get_root_window(), он вернет все приложения gtk, через которые вам придется пройтись по циклу, чтобы найти свое собственное, то есть: for i in gtk.gdk.screen_get_default().get_root_window().get_children(). Я обновил свой пост рабочим примером, надеюсь, вы сможете заставить эту функцию работать в своем приложении. - person vls; 05.10.2010
comment
Возможно ли, что вы тестируете оконный менеджер, который не поддерживает эти свойства? - person Havoc P; 05.10.2010
comment
Фантастика! Понятно! Спасибо всем, особенно, всеменов! - person Josh; 05.10.2010
comment
Для всех будущих читателей этого вопроса кажется, что свойства должны быть установлены ПОСЛЕ вызова метода show(). Я застрял на этом около часа. - person Josh; 06.10.2010
comment
Обновленный ответ с выделением необходимости звонить show() перед property_change(). - person vls; 06.10.2010
comment
@vls: у вас есть идеи, как сделать то же самое с Qt4? См. ветку. Спасибо. - person neydroydrec; 08.05.2011
comment
В Gtk+3 Gtk.Window.window (или Gtk.Window.get_top_level().window) не имеет метода property_change(). У меня не получилось портировать. У вас есть какие-нибудь подсказки? В противном случае приведенный выше ответ будет считаться устаревшим, поскольку Gtk+3 заменит Gtk+2. Спасибо. - person neydroydrec; 22.05.2011
comment
Привет еще раз: я до сих пор Gdk.property_change(self.window.get_toplevel().window, "_NET_WM_STRUT", "CARDINAL", 32, Gdk.PropMode.REPLACE, [0,0,24,0], 4) использовал PyGI с Gtk+3, но это не сработает, потому что arg 1 и 2 должны быть типа Gdk.Atom, а метод Gdk.atom_intern() недоступен (?), поэтому я могу' т сделать преобразование. Также я не уверен насчет arg -1. См. документ по Свойствам и атомам Gdk. - person neydroydrec; 22.05.2011
comment
Возможно ли это противоположное этому? Я пытаюсь сделать так, чтобы мое полноэкранное окно перекрывало док-станцию, но это не всегда будет делаться. - person yatg; 23.07.2015