Merge lp:~ted/libdbusmenu/theme-in-gtk into lp:libdbusmenu/0.5

Proposed by Ted Gould
Status: Merged
Merged at revision: 264
Proposed branch: lp:~ted/libdbusmenu/theme-in-gtk
Merge into: lp:libdbusmenu/0.5
Diff against target: 264 lines (+201/-0)
2 files modified
libdbusmenu-glib/client.c (+29/-0)
libdbusmenu-gtk/client.c (+172/-0)
To merge this branch: bzr merge lp:~ted/libdbusmenu/theme-in-gtk
Reviewer Review Type Date Requested Status
Conor Curran (community) Approve
Review via email: mp+52878@code.launchpad.net

Description of the change

Making it so that icon theme paths are handled in GTK Client.

To post a comment you must log in.
Revision history for this message
Conor Curran (cjcurran) :
review: Approve

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'libdbusmenu-glib/client.c'
2--- libdbusmenu-glib/client.c 2011-03-10 00:43:07 +0000
3+++ libdbusmenu-glib/client.c 2011-03-10 16:23:56 +0000
4@@ -1056,10 +1056,39 @@
5 }
6
7 priv->text_direction = dbusmenu_text_direction_get_value_from_nick(g_variant_get_string(str, NULL));
8+ g_object_notify(G_OBJECT(user_data), DBUSMENU_CLIENT_PROP_TEXT_DIRECTION);
9
10 g_variant_unref(textdir);
11 }
12
13+ /* Check the status if available */
14+ GVariant * status = g_dbus_proxy_get_cached_property(priv->menuproxy, "Status");
15+ if (textdir != NULL) {
16+ GVariant * str = status;
17+ if (g_variant_is_of_type(str, G_VARIANT_TYPE_VARIANT)) {
18+ str = g_variant_get_variant(str);
19+ }
20+
21+ priv->status = dbusmenu_status_get_value_from_nick(g_variant_get_string(str, NULL));
22+ g_object_notify(G_OBJECT(user_data), DBUSMENU_CLIENT_PROP_STATUS);
23+
24+ g_variant_unref(status);
25+ }
26+
27+ /* Get the icon theme directories if available */
28+ GVariant * icon_dirs = g_dbus_proxy_get_cached_property(priv->menuproxy, "IconThemePath");
29+ if (icon_dirs != NULL) {
30+ if (priv->icon_dirs != NULL) {
31+ g_strfreev(priv->icon_dirs);
32+ priv->icon_dirs = NULL;
33+ }
34+
35+ priv->icon_dirs = g_variant_dup_strv(icon_dirs, NULL);
36+ g_signal_emit(G_OBJECT(client), signals[ICON_THEME_DIRS], 0, priv->icon_dirs, TRUE);
37+
38+ g_variant_unref(icon_dirs);
39+ }
40+
41 /* If we get here, we don't need the DBus proxy */
42 if (priv->dbusproxy != 0) {
43 g_bus_unwatch_name(priv->dbusproxy);
44
45=== modified file 'libdbusmenu-gtk/client.c'
46--- libdbusmenu-gtk/client.c 2011-03-10 00:43:07 +0000
47+++ libdbusmenu-gtk/client.c 2011-03-10 16:23:56 +0000
48@@ -38,9 +38,12 @@
49
50 /* Private */
51 struct _DbusmenuGtkClientPrivate {
52+ GStrv old_themedirs;
53 GtkAccelGroup * agroup;
54 };
55
56+GHashTable * theme_dir_db = NULL;
57+
58 #define DBUSMENU_GTKCLIENT_GET_PRIVATE(o) (DBUSMENU_GTKCLIENT(o)->priv)
59 #define USE_FALLBACK_PROP "use-fallback"
60
61@@ -54,6 +57,8 @@
62 static void delete_child (DbusmenuMenuitem * mi, DbusmenuMenuitem * child, DbusmenuGtkClient * gtkclient);
63 static void move_child (DbusmenuMenuitem * mi, DbusmenuMenuitem * child, guint new, guint old, DbusmenuGtkClient * gtkclient);
64 static void item_activate (DbusmenuClient * client, DbusmenuMenuitem * mi, guint timestamp, gpointer userdata);
65+static void theme_dir_changed (DbusmenuClient * client, GStrv theme_dirs, gpointer userdata);
66+static void remove_theme_dirs (GtkIconTheme * theme, GStrv dirs);
67
68 static gboolean new_item_normal (DbusmenuMenuitem * newitem, DbusmenuMenuitem * parent, DbusmenuClient * client, gpointer user_data);
69 static gboolean new_item_seperator (DbusmenuMenuitem * newitem, DbusmenuMenuitem * parent, DbusmenuClient * client, gpointer user_data);
70@@ -89,6 +94,23 @@
71 DbusmenuGtkClientPrivate * priv = DBUSMENU_GTKCLIENT_GET_PRIVATE(self);
72
73 priv->agroup = NULL;
74+ priv->old_themedirs = NULL;
75+
76+ /* We either build the theme db or we get a reference
77+ to it. This way when all clients die the hashtable
78+ will be free'd as well. */
79+ if (theme_dir_db == NULL) {
80+ theme_dir_db = g_hash_table_new_full(g_str_hash, g_str_equal, g_free, NULL);
81+
82+ /* NOTE: We're adding an extra ref here because there
83+ is no way to clear the pointer when the hash table
84+ dies, so it's safer to keep the hash table around
85+ forever than not know if it's free'd or not. Patch
86+ submitted to GLib. */
87+ g_hash_table_ref(theme_dir_db);
88+ } else {
89+ g_hash_table_ref(theme_dir_db);
90+ }
91
92 dbusmenu_client_add_type_handler(DBUSMENU_CLIENT(self), DBUSMENU_CLIENT_TYPES_DEFAULT, new_item_normal);
93 dbusmenu_client_add_type_handler(DBUSMENU_CLIENT(self), DBUSMENU_CLIENT_TYPES_SEPARATOR, new_item_seperator);
94@@ -96,6 +118,9 @@
95 /* TODO: I think these can be handled in the class... */
96 g_signal_connect(G_OBJECT(self), DBUSMENU_CLIENT_SIGNAL_NEW_MENUITEM, G_CALLBACK(new_menuitem), NULL);
97 g_signal_connect(G_OBJECT(self), DBUSMENU_CLIENT_SIGNAL_ITEM_ACTIVATE, G_CALLBACK(item_activate), NULL);
98+ g_signal_connect(G_OBJECT(self), DBUSMENU_CLIENT_SIGNAL_ICON_THEME_DIRS_CHANGED, G_CALLBACK(theme_dir_changed), NULL);
99+
100+ theme_dir_changed(DBUSMENU_CLIENT(self), dbusmenu_client_get_icon_paths(DBUSMENU_CLIENT(self)), NULL);
101
102 return;
103 }
104@@ -111,6 +136,18 @@
105 priv->agroup = NULL;
106 }
107
108+ if (priv->old_themedirs) {
109+ remove_theme_dirs(gtk_icon_theme_get_default(), priv->old_themedirs);
110+ g_strfreev(priv->old_themedirs);
111+ priv->old_themedirs = NULL;
112+ }
113+
114+ if (theme_dir_db != NULL) {
115+ g_hash_table_unref(theme_dir_db);
116+ } else {
117+ g_assert_not_reached();
118+ }
119+
120 G_OBJECT_CLASS (dbusmenu_gtkclient_parent_class)->dispose (object);
121 return;
122 }
123@@ -124,6 +161,141 @@
124 return;
125 }
126
127+/* Add a theme directory to the table and the theme's list of available
128+ themes to use. */
129+static void
130+theme_dir_ref (GtkIconTheme * theme, GHashTable * db, const gchar * dir)
131+{
132+ g_return_if_fail(db != NULL);
133+ g_return_if_fail(theme != NULL);
134+ g_return_if_fail(dir != NULL);
135+
136+ int count = 0;
137+ if ((count = GPOINTER_TO_INT(g_hash_table_lookup(db, dir))) != 0) {
138+ /* It exists so what we need to do is increase the ref
139+ count of this dir. */
140+ count++;
141+ } else {
142+ /* It doesn't exist, so we need to add it to the table
143+ and to the search path. */
144+ gtk_icon_theme_append_search_path(gtk_icon_theme_get_default(), dir);
145+ g_debug("\tAppending search path: %s", dir);
146+ count = 1;
147+ }
148+
149+ g_hash_table_insert(db, g_strdup(dir), GINT_TO_POINTER(count));
150+
151+ return;
152+}
153+
154+/* Unreference the theme directory, and if it's count goes to zero then
155+ we need to remove it from the search path. */
156+static void
157+theme_dir_unref (GtkIconTheme * theme, GHashTable * db, const gchar * dir)
158+{
159+ g_return_if_fail(db != NULL);
160+ g_return_if_fail(theme != NULL);
161+ g_return_if_fail(dir != NULL);
162+
163+ /* Grab the count for this dir */
164+ int count = GPOINTER_TO_INT(g_hash_table_lookup(db, dir));
165+
166+ /* Is this a simple deprecation, if so, we can just lower the
167+ number and move on. */
168+ if (count > 1) {
169+ count--;
170+ g_hash_table_insert(db, g_strdup(dir), GINT_TO_POINTER(count));
171+ return;
172+ }
173+
174+ /* Try to remove it from the hash table, this makes sure
175+ that it existed */
176+ if (!g_hash_table_remove(db, dir)) {
177+ g_warning("Unref'd a directory that wasn't in the theme dir hash table.");
178+ return;
179+ }
180+
181+ gchar ** paths;
182+ gint path_count;
183+
184+ gtk_icon_theme_get_search_path(theme, &paths, &path_count);
185+
186+ gint i;
187+ gboolean found = FALSE;
188+ for (i = 0; i < path_count; i++) {
189+ if (found) {
190+ /* If we've already found the right entry */
191+ paths[i - 1] = paths[i];
192+ } else {
193+ /* We're still looking, is this the one? */
194+ if (!g_strcmp0(paths[i], dir)) {
195+ found = TRUE;
196+ /* We're freeing this here as it won't be captured by the
197+ g_strfreev() below as it's out of the array. */
198+ g_free(paths[i]);
199+ }
200+ }
201+ }
202+
203+ /* If we found one we need to reset the path to
204+ accomidate the changes */
205+ if (found) {
206+ paths[path_count - 1] = NULL; /* Clear the last one */
207+ gtk_icon_theme_set_search_path(theme, (const gchar **)paths, path_count - 1);
208+ }
209+
210+ g_strfreev(paths);
211+
212+ return;
213+}
214+
215+/* Unregister this list of theme directories */
216+static void
217+remove_theme_dirs (GtkIconTheme * theme, GStrv dirs)
218+{
219+ g_return_if_fail(GTK_ICON_THEME(theme));
220+ g_return_if_fail(dirs != NULL);
221+
222+ int dir;
223+
224+ for (dir = 0; dirs[dir] != NULL; dir++) {
225+ theme_dir_unref(theme, theme_dir_db, dirs[dir]);
226+ }
227+
228+ return;
229+}
230+
231+/* Called when the theme directories are changed by the
232+ server part of things. */
233+static void
234+theme_dir_changed (DbusmenuClient * client, GStrv theme_dirs, gpointer userdata)
235+{
236+ DbusmenuGtkClientPrivate * priv = DBUSMENU_GTKCLIENT_GET_PRIVATE(client);
237+ GtkIconTheme * theme = gtk_icon_theme_get_default();
238+
239+ /* Ref the new directories */
240+ if (theme_dirs != NULL) {
241+ int dir;
242+ for (dir = 0; theme_dirs[dir] != NULL; dir++) {
243+ theme_dir_ref(theme, theme_dir_db, theme_dirs[dir]);
244+ }
245+ }
246+
247+ /* Unref the old ones */
248+ if (priv->old_themedirs) {
249+ remove_theme_dirs(theme, priv->old_themedirs);
250+ g_strfreev(priv->old_themedirs);
251+ priv->old_themedirs = NULL;
252+ }
253+
254+ /* Copy the new to the old */
255+ if (theme_dirs != NULL) {
256+ priv->old_themedirs = g_strdupv(theme_dirs);
257+ }
258+
259+ return;
260+}
261+
262 /* Structure for passing data to swap_agroup */
263 typedef struct _swap_agroup_t swap_agroup_t;
264 struct _swap_agroup_t {

Subscribers

People subscribed via source and target branches