1 /*
2  * SPDX-FileCopyrightText: 2020 Mikhail Zolotukhin <zomial@protonmail.com>
3  *
4  * SPDX-License-Identifier: GPL-2.0-only OR GPL-3.0-only OR LicenseRef-KDE-Accepted-GPL
5  */
6 
7 #include <gdk/gdk.h>
8 #include <gio/gio.h>
9 #include <glib.h>
10 #include <gtk/gtk.h>
11 
12 #define UNUSED(x) (void)(x)
13 
14 gchar *window_decorations_css_path;
15 GFile *window_decorations_css_file;
16 
17 GFileMonitor *window_decorations_css_monitor;
18 
19 GtkCssProvider *css_provider;
20 
21 void manage_css_provider(GFileMonitor *monitor, GFile *file, GFile *other_file, GFileMonitorEvent event_type, gpointer user_data);
22 void reload_css_provider();
23 void remove_css_provider();
24 int theme_is_breeze();
25 void theme_changed(GtkSettings *settings, GParamSpec *param_spec, void *user_data);
26 
gtk_module_init(gint * argc,gchar *** argv[])27 __attribute__((visibility("default"))) void gtk_module_init(gint *argc, gchar ***argv[])
28 {
29     UNUSED(argc);
30     UNUSED(argv);
31 
32     window_decorations_css_path = g_strconcat(g_get_user_config_dir(), "/gtk-3.0/window_decorations.css", NULL);
33     window_decorations_css_file = g_file_new_for_path(window_decorations_css_path);
34 
35     window_decorations_css_monitor = g_file_monitor_file(window_decorations_css_file, G_FILE_MONITOR_NONE, NULL, NULL);
36 
37     css_provider = NULL;
38 
39     g_signal_connect(window_decorations_css_monitor, "changed", G_CALLBACK(manage_css_provider), NULL);
40     g_signal_connect(gtk_settings_get_default(), "notify::gtk-theme-name", G_CALLBACK(theme_changed), NULL);
41 
42     reload_css_provider();
43 }
44 
manage_css_provider(GFileMonitor * monitor,GFile * file,GFile * other_file,GFileMonitorEvent event_type,gpointer user_data)45 void manage_css_provider(GFileMonitor *monitor, GFile *file, GFile *other_file, GFileMonitorEvent event_type, gpointer user_data)
46 {
47     UNUSED(monitor);
48     UNUSED(file);
49     UNUSED(other_file);
50     UNUSED(user_data);
51 
52     if (event_type == G_FILE_MONITOR_EVENT_CREATED || event_type == G_FILE_MONITOR_EVENT_CHANGED) {
53         reload_css_provider();
54     } else if (event_type == G_FILE_MONITOR_EVENT_DELETED) {
55         remove_css_provider();
56     }
57 }
58 
reload_css_provider()59 void reload_css_provider()
60 {
61     remove_css_provider();
62 
63     if (!theme_is_breeze()) {
64         return;
65     }
66 
67     css_provider = gtk_css_provider_new();
68 
69     gtk_style_context_add_provider_for_screen(gdk_screen_get_default(), GTK_STYLE_PROVIDER(css_provider), GTK_STYLE_PROVIDER_PRIORITY_USER + 1);
70     if (g_file_query_exists(window_decorations_css_file, NULL)) {
71         gtk_css_provider_load_from_file(css_provider, window_decorations_css_file, NULL);
72     }
73 }
74 
remove_css_provider()75 void remove_css_provider()
76 {
77     if (!css_provider) {
78         return;
79     }
80     gtk_style_context_remove_provider_for_screen(gdk_screen_get_default(), GTK_STYLE_PROVIDER(css_provider));
81     g_clear_object(&css_provider);
82 }
83 
theme_is_breeze()84 int theme_is_breeze()
85 {
86     GtkSettings *settings = gtk_settings_get_default();
87     char *theme_name = NULL;
88     g_object_get(settings, "gtk-theme-name", &theme_name, NULL);
89     if (!theme_name) {
90         return 0;
91     }
92     int ret = !strcmp(theme_name, "Breeze");
93     g_free(theme_name);
94     return ret;
95 }
96 
theme_changed(GtkSettings * settings,GParamSpec * param_spec,void * user_data)97 void theme_changed(GtkSettings *settings, GParamSpec *param_spec, void *user_data)
98 {
99     UNUSED(settings);
100     UNUSED(param_spec);
101     UNUSED(user_data);
102     reload_css_provider();
103 }
104