Как нарисовать кнопки окна из Gtk.Context в gjs

Я пытаюсь извлечь кнопки 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/[email protected]"),
                                  url("assets/[email protected]"),
                                  url("assets/[email protected]"));
}

И путь, который генерирует мой код, имеет следующий формат:

.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 ничего не отображается. Ширина и высота области рисования соответствует размеру панели оболочки gnome 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


person lestcape    schedule 13.05.2018    source источник


Ответы (1)


Имя элемента в CSS — это «имя CSS», а не имя класса. Вы можете установить имя CSS в преамбуле вашего класса:

const GtkButton = new GObject.Class({
    Name: 'button',
    CssName: 'button',
    Extends: Gtk.Button,
});

или, в классах нового стиля,

const GtkButton = GObject.registerClass({
    CssName: 'button',
}, class MyButton extends Gtk.Button {
});
person ptomato    schedule 27.05.2018
comment
В определении css я использовал цвет рамки: #333333; (нет в определении по умолчанию), то context.get_border_color(Gtk.StateFlags.NORMAL); дайте мне значение цвета, чтобы узнать, подключен ли я к стилю CSS или нет. Если я установлю CssName: 'button', цвет, который вернет мне, будет 255, 255, 255, 255, поэтому я не подключен, но если я использую GTypeName: 'button', это вернет мне цвет 51, 51 , 51, 255, Итак, это указывает на то, что я подключен к правильному стилю CSS. Обратите внимание, что это работает только с последними gjs, в более старых версиях я всегда получаю не цвет. Итак, спасибо, но CssName не будет работать. - person lestcape; 29.05.2018
comment
Вот рабочий пример: github.com/lestcape/metacity-buttons (с решением которые работают для меня). Вероятно, легко заменить это реализацией Gtk.WidgetPath, и вы сами увидите все проблемы. Если вы считаете это ошибкой, я могу открыть вопрос в gjs. - person lestcape; 29.05.2018
comment
Я думаю, это изменилось с имени gtype на имя CSS в GTK 3.20. Так что, если вы работаете в GTK 3.18, все будет иначе. Где CSS в вашем примере? - person ptomato; 29.05.2018
comment
Я использовал пакет 3.22.30-1ubuntu1, и он не работает. Я просто редактирую тему окружения напрямую: /usr/share/themes/Ambiance/gtk-3.20/gtk-widgets.css, а затем устанавливаю тему Ambiance в инструментах настройки gnome. То же самое с/без добавления Gtk.CssProvider. По умолчанию используется текущий активный Gtk.CssProvider и это текущая активная тема. Предыдущая ссылка — это расширение для извлечения оконных кнопок на основе текущей активной темы. Посмотрите видео о расширении: youtube.com/watch?v=7CnoMEM44Do. - person lestcape; 29.05.2018