2016-05-28 2 views
4

Я работаю над простым оконным менеджером в c с libxcb, и я пытаюсь украсить окно с помощью кнопок заголовка, значка и кнопок min/max/close.Как нарисовать заголовок с XCB

Я тестирую свой wm в Xephyr. Я могу создать новое окно xterm, переместить его и изменить его размер. Но теперь я хотел бы украсить новое окно xterm (или любое другое приложение, если на то пошло), так что он имеет кнопки заголовка, значка и кнопки min/max/close.

На моей машине Linux я только что установил тему Gtk, и, если я запустил Firefox, окно будет оформлено после того, как я установил эту тему в моих настройках. Поэтому в этом случае я считаю, что Gtk применяет декорации окон. Как это работает?

Я прочитал, что свойство окна EWMH, _NET_WM_WINDOW_TYPE, может использоваться, чтобы определить, как обрабатывать украшение вашего окна. Поэтому я думаю, что я могу проверить, есть ли тип окна _NET_WM_WINDOW_TYPE_NORMAL, получить WM_NAME из приложения, а затем вручную нарисовать над ним заголовок.

Это как вы должны нарисовать ваши украшения в обычном порядке? Или я могу использовать Gtk (или что-то еще) для этого?

ответ

5

Так что в этом случае я думаю, что это Gtk, который применяет оконные украшения. Как это работает?

Исправить. Приложения GTK сообщают диспетчеру окон не украшать их, установив ширину границы на 0. Теперь мое предложение будет состоять в том, чтобы реализовать это: если окно устанавливает ширину границы 0, игнорируйте его. Вначале я бы не стал беспокоиться ни о чем другом. На самом деле вы даже можете игнорировать этот намек.

Я прочитал, что свойство окна EWMH [...]

Не связывайтесь с EWMH сейчас. Просто украсьте все управляемые окна, которые не устанавливают границу на 0. Кроме того, я не вижу веской причины, почему другие типы окон, такие как диалоги, не должны быть украшены; Я не думаю, что оконные менеджеры действительно используют это свойство, чтобы определить это, но я могу только сказать наверняка пару.

Это как вы должны нарисовать свои украшения в обычном порядке? Или я могу использовать Gtk (или что-то еще) для этого?

В то время как вы явно не просили об этом, последнее предложение в этой цитате говорит мне, что вы не можете полностью понять, как работают украшения. Самый распространенный способ, и я настоятельно рекомендую вам сделать это так, называется reparenting.

Reparenting означает, что при управлении окно, создать новое окно (которое, конечно, вы должны не управлять как обычное окно клиента) называется окно кадра, а затем изменит родителя окно клиента в окно фрейма , Таким образом, фактическое окно верхнего уровня - это окно кадра, принадлежащее диспетчеру окон; клиентское окно (окно, с которым пользователь взаимодействует) является его прямым потомком.

Теперь вы просто сделаете окно рамы немного больше, чем окно клиента, и правильно разместите окно клиента внутри него. Конечно, вам нужно отслеживать изменения размера окна клиента и действовать на них.

Итак, почему мы создали это окно кадра? Просто! Потому что вы можете создать pixmap, который вы используете для него, и на котором вы рисуете свой заголовок. Это лучше, чем рисовать непосредственно на дочернем окне, потому что вы не возитесь с окном, которое у вас фактически нет.

Рисование может быть выполнено с помощью «сырых» и простых вызовов, таких как xcb_poly_fill_rectangle, или вы можете использовать более сложный подход, например, используя библиотеку, такую ​​как cairo (которую я бы рекомендовал). Например, диспетчер окон i3 использует простую абстракцию, которая поддерживает как флаг компиляции (libi3/draw_util.c).

Этот подход к рассмотрению является причиной, по которой инструменты, такие как xwininfo или xprop, имеют опцию -frame. По умолчанию эти инструменты фактически игнорируют окно кадра и спускаются в окно клиента, в значительной степени скрывая тот факт, что есть окно кадра. Просто попробуйте xprop и xprop -frame в том же окне, и вы увидите, что окно кадра имеет гораздо меньше информации, прикрепленной к нему.

После того, как вы усовершенствуете и рисуете на месте, вы можете больше думать о случаях, когда вам не нужно/хотите украсить окно. Учитывая, что здесь нужно немного отслеживать, я думаю, что реализация этого вначале заставит вас заняться какое-то время. Я настоятельно рекомендую изучить код других простейших оконных менеджеров, которые отныне.

+0

О, я не знал о том, как репарировать, спасибо. Я буду использовать это, чтобы рисовать собственный заголовок. Но я не понимаю, как я могу показать тему GTK для приложений GTK. Нужно ли мне что-либо делать (кроме того, что я не рисую собственные украшения), если приложение устанавливает ширину рамки до 0? – Carlito

+0

Нет, GTK - это просто библиотека, которую использует клиент. Диспетчер окон не участвует в рендеринге самого окна клиента, это зависит от клиента, который в этом случае использует GTK для упрощения. Вам не о чем беспокоиться. –

+0

Самый распространенный способ сделать это - повторять. Какие еще существуют способы рисования заголовка? –