Я пытаюсь извлечь кнопки Windows из текущей активной темы gtk и визуализировать ее в контексте cairo в gjs для использования в Gnome-Global-Menu (https://gitlab.com/lestcape/Gnome-Global-AppMenu). В качестве примера я есть один код, который я использую, чтобы извлечь кнопку закрытия.
this.actor = new St.DrawingArea();
this.actor.connect('repaint', Lang.bind(this, this._onRepaint));
_onRepaint: function(area) {
let cr = area.get_context();
let [width, height] = area.get_surface_size();
let provider = Gtk.CssProvider.get_default();
let path = new Gtk.WidgetPath();
let pos1 = path.append_type(Gtk.HeaderBar);
let pos2 = path.append_type(Gtk.Button);
path.iter_add_class(pos1, 'titlebar');
path.iter_add_class(pos2, 'titlebutton');
path.iter_add_class(pos2, 'close');
let context = new Gtk.StyleContext();
context.set_screen(Gdk.Screen.get_default());
context.set_path(path);
context.save();
context.set_state(Gtk.StateFlags.NORMAL);
Gtk.render_background(context, cr, 0, 0, width, height);
Gtk.render_frame(context, cr, 0, 0, width, height);
context.restore();
},
Это было мое первое приближение, но оно не работает. Я обнаружил, что CSS внутри темы Ambiance выглядит примерно так:
.titlebar button.titlebutton.close {
border-color: #333333;
color: #323112;
-gtk-icon-shadow: 0 1px rgba(255, 255, 255, 0.25);
background-image: -gtk-scaled(url("assets/windowbutton-close.png"),
url("assets/windowbutton-close@2.png"),
url("assets/windowbutton-close@3.png"),
url("assets/windowbutton-close@4.png"));
}
И путь, по которому генерируется мой код, имеет следующий формат:
.titlebar GtkButton.titlebutton.close
Это произошло потому, что GType Gtk.Button в gjs возвращает мне GtkButton, а не кнопку, как в теме. Итак, я создаю вспомогательный класс:
const GtkButton = new GObject.Class({
Name: 'button',
GTypeName: 'button',
Extends: Gtk.Button,
_init: function(params) {
this.parent(params);
},
});
А потом вместо:
let pos2 = path.append_type(Gtk.Button);
Я добавляю:
let pos2 = path.append_type(GtkButton);
Тогда мой путь и свойства css совпадают, но в моем контексте cairo также ничего не отображается. Ширина и высота области рисования - это размер панели оболочки гнома 27 пикселей.
Итак, чего здесь не хватает?
С другой стороны, если я получаю контекст непосредственно из Gtk.widgets, то, что я хочу, просто работает:
let headerWidget = new Gtk.HeaderBar();
let buttonWidget = new Gtk.Button();
let context = headerWidget.get_style_context();
context.add_class('titlebar');
headerWidget.add(buttonWidget);
context = buttonWidget.get_style_context();
context.add_class('titlebutton');
context.add_class('close');
Пример, реализованный с использованием последнего кода, приведен здесь: https://gitlab.com/lestcape/metacity-buttons, а видео, демонстрирующее его работу, можно посмотреть здесь: https://www.youtube.com/watch?v=7CnoMEM44Do&t=18s