summaryrefslogtreecommitdiff
path: root/lib/astal/gtk3/src/widget/widget.vala
blob: 2506bc8b77105d61765dbe722cfcf44231563a8f (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
namespace Astal {
private class Css {
    private static HashTable<Gtk.Widget, Gtk.CssProvider> _providers;
    public static HashTable<Gtk.Widget, Gtk.CssProvider> providers {
        get {
            if (_providers == null) {
                _providers = new HashTable<Gtk.Widget, Gtk.CssProvider>(
                    (w) => (uint)w,
                    (a, b) => a == b);
            }

            return _providers;
        }
    }
}

private void remove_provider(Gtk.Widget widget) {
    var providers = Css.providers;

    if (providers.contains(widget)) {
        var p = providers.get(widget);
        widget.get_style_context().remove_provider(p);
        providers.remove(widget);
        p.dispose();
    }
}

public void widget_set_css(Gtk.Widget widget, string css) {
    var providers = Css.providers;

    if (providers.contains(widget)) {
        remove_provider(widget);
    } else {
        widget.destroy.connect(() => {
            remove_provider(widget);
        });
    }

    var style = !css.contains("{") || !css.contains("}")
        ? "* { ".concat(css, "}") : css;

    var p = new Gtk.CssProvider();
    widget.get_style_context()
        .add_provider(p, Gtk.STYLE_PROVIDER_PRIORITY_USER);

    try {
        p.load_from_data(style, style.length);
        providers.set(widget, p);
    } catch (Error err) {
        warning(err.message);
    }
}

public string widget_get_css(Gtk.Widget widget) {
    var providers = Css.providers;

    if (providers.contains(widget))
        return providers.get(widget).to_string();

    return "";
}

public void widget_set_class_names(Gtk.Widget widget, string[] class_names) {
    foreach (var name in widget_get_class_names(widget))
        widget_toggle_class_name(widget, name, false);

    foreach (var name in class_names)
        widget_toggle_class_name(widget, name, true);
}

public List<weak string> widget_get_class_names(Gtk.Widget widget) {
    return widget.get_style_context().list_classes();
}

public void widget_toggle_class_name(
    Gtk.Widget widget,
    string class_name,
    bool condition = true
) {
    var c = widget.get_style_context();
    if (condition)
        c.add_class(class_name);
    else
        c.remove_class(class_name);
}

private class Cursor {
    private static HashTable<Gtk.Widget, string> _cursors;
    public static HashTable<Gtk.Widget, string> cursors {
        get {
            if (_cursors == null) {
                _cursors = new HashTable<Gtk.Widget, string>(
                    (w) => (uint)w,
                    (a, b) => a == b);
            }
            return _cursors;
        }
    }
}

private void widget_setup_cursor(Gtk.Widget widget) {
    widget.add_events(Gdk.EventMask.ENTER_NOTIFY_MASK);
    widget.add_events(Gdk.EventMask.LEAVE_NOTIFY_MASK);
    widget.enter_notify_event.connect(() => {
        widget.get_window().set_cursor(
            new Gdk.Cursor.from_name(
                Gdk.Display.get_default(),
                Cursor.cursors.get(widget)));
        return false;
    });
    widget.leave_notify_event.connect(() => {
        widget.get_window().set_cursor(
            new Gdk.Cursor.from_name(
                Gdk.Display.get_default(),
                "default"));
        return false;
    });
    widget.destroy.connect(() => {
        if (Cursor.cursors.contains(widget))
            Cursor.cursors.remove(widget);
    });
}

public void widget_set_cursor(Gtk.Widget widget, string cursor) {
    if (!Cursor.cursors.contains(widget))
        widget_setup_cursor(widget);

    Cursor.cursors.set(widget, cursor);
}

public string widget_get_cursor(Gtk.Widget widget) {
    return Cursor.cursors.get(widget);
}

private class ClickThrough {
    private static HashTable<Gtk.Widget, bool> _click_through;
    public static HashTable<Gtk.Widget, bool> click_through {
        get {
            if (_click_through == null) {
                _click_through = new HashTable<Gtk.Widget, bool>(
                    (w) => (uint)w,
                    (a, b) => a == b);
            }
            return _click_through;
        }
    }
}

public void widget_set_click_through(Gtk.Widget widget, bool click_through) {
    ClickThrough.click_through.set(widget, click_through);
    widget.input_shape_combine_region(click_through ? new Cairo.Region() : null);
}

public bool widget_get_click_through(Gtk.Widget widget) {
    return ClickThrough.click_through.get(widget);
}
}