Merge lp:~3v1n0/bamf/better-wmclass-filter into lp:bamf/0.4

Proposed by Marco Trevisan (Treviño) on 2012-04-29
Status: Merged
Approved by: Marco Trevisan (Treviño) on 2012-05-22
Approved revision: 479
Merged at revision: 466
Proposed branch: lp:~3v1n0/bamf/better-wmclass-filter
Merge into: lp:bamf/0.4
Prerequisite: lp:~3v1n0/bamf/desktopless-webapps-fix
Diff against target: 434 lines (+140/-75)
3 files modified
src/bamf-application.c (+29/-19)
src/bamf-matcher.c (+108/-56)
src/bamf-matcher.h (+3/-0)
To merge this branch: bzr merge lp:~3v1n0/bamf/better-wmclass-filter
Reviewer Review Type Date Requested Status
Jason Smith (community) 2012-04-29 Approve on 2012-05-22
Review via email: mp+104036@code.launchpad.net

Commit message

BamfMatcher: use both instance and class names for matching WMClass

Also, filter out the .desktop files that have a defined StartupWMClass
that doesn't match with our .desktop file.

Description of the change

We use both WMClass instance and class name to match proper .desktop files, also we filter out from possible_desktop list the .desktop files that have defined a wmclass that does not match with the one of the target window.

This allow to make both the custom applications .desktop files to work correctly and the web applications to be matched as new ones.

Plus, favorites are used only if their class matches.

To post a comment you must log in.
Jason Smith (jassmith) wrote :

Looks good, nothing too scary.

review: Approve
Unity Merger (unity-merger) wrote :

The prerequisite lp:~3v1n0/bamf/desktopless-webapps-fix has not yet been merged into lp:bamf.

Unity Merger (unity-merger) wrote :

Attempt to merge into lp:bamf failed due to conflicts:

text conflict in src/bamf-matcher.c

lp:~3v1n0/bamf/better-wmclass-filter updated on 2012-05-22
479. By Marco Trevisan (Treviño) on 2012-05-22

Merging with trunk

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'src/bamf-application.c'
2--- src/bamf-application.c 2012-04-26 06:16:01 +0000
3+++ src/bamf-application.c 2012-05-22 16:24:22 +0000
4@@ -120,17 +120,20 @@
5 if (self->priv->desktop_file)
6 {
7 keyfile = g_key_file_new();
8- if (!g_key_file_load_from_file(keyfile, self->priv->desktop_file, G_KEY_FILE_NONE, NULL)) {
9+
10+ if (!g_key_file_load_from_file(keyfile, self->priv->desktop_file, G_KEY_FILE_NONE, NULL))
11+ {
12 g_key_file_free(keyfile);
13- return;
14- }
15+ return;
16+ }
17
18 desktop = g_desktop_app_info_new_from_keyfile (keyfile);
19
20- if (!G_IS_APP_INFO (desktop)) {
21- g_key_file_free(keyfile);
22- return;
23- }
24+ if (!G_IS_APP_INFO (desktop))
25+ {
26+ g_key_file_free(keyfile);
27+ return;
28+ }
29
30 gicon = g_app_info_get_icon (G_APP_INFO (desktop));
31
32@@ -139,14 +142,15 @@
33 if (gicon)
34 icon = g_icon_to_string (gicon);
35
36- if (g_key_file_has_key(keyfile, G_KEY_FILE_DESKTOP_GROUP, STUB_KEY, NULL)) {
37- /* This will error to return false, which is okay as it seems
38- unlikely anyone will want to set this flag except to turn
39- off the stub menus. */
40- self->priv->show_stubs = g_key_file_get_boolean (keyfile,
41- G_KEY_FILE_DESKTOP_GROUP,
42- STUB_KEY, NULL);
43- }
44+ if (g_key_file_has_key(keyfile, G_KEY_FILE_DESKTOP_GROUP, STUB_KEY, NULL))
45+ {
46+ /* This will error to return false, which is okay as it seems
47+ unlikely anyone will want to set this flag except to turn
48+ off the stub menus. */
49+ self->priv->show_stubs = g_key_file_get_boolean (keyfile,
50+ G_KEY_FILE_DESKTOP_GROUP,
51+ STUB_KEY, NULL);
52+ }
53
54 if (g_key_file_has_key (keyfile, G_KEY_FILE_DESKTOP_GROUP, "X-GNOME-FullName", NULL))
55 {
56@@ -489,11 +493,12 @@
57 }
58
59 static char *
60-bamf_application_favorite_from_list (BamfApplication *self, GList *list)
61+bamf_application_favorite_from_list (BamfApplication *self, GList *desktop_list)
62 {
63 BamfMatcher *matcher;
64 GList *favs, *l;
65 char *result = NULL;
66+ const char *desktop_class;
67
68 g_return_val_if_fail (BAMF_IS_APPLICATION (self), NULL);
69
70@@ -504,10 +509,15 @@
71 {
72 for (l = favs; l; l = l->next)
73 {
74- if (g_list_find_custom (list, l->data, (GCompareFunc) g_strcmp0))
75+ if (g_list_find_custom (desktop_list, l->data, (GCompareFunc) g_strcmp0))
76 {
77- result = l->data;
78- break;
79+ desktop_class = bamf_matcher_get_desktop_file_class (matcher, l->data);
80+
81+ if (!desktop_class || g_strcmp0 (self->priv->wmclass, desktop_class) == 0)
82+ {
83+ result = l->data;
84+ break;
85+ }
86 }
87 }
88 }
89
90=== modified file 'src/bamf-matcher.c'
91--- src/bamf-matcher.c 2012-05-22 15:10:26 +0000
92+++ src/bamf-matcher.c 2012-05-22 16:24:22 +0000
93@@ -659,9 +659,11 @@
94 }
95
96 static gboolean
97-exec_string_should_be_processed (BamfMatcher *self,
98- char *exec)
99+exec_string_should_be_processed (const char *exec)
100 {
101+ if (!exec)
102+ return TRUE;
103+
104 return !g_str_has_prefix (exec, "ooffice") && !g_str_has_prefix (exec, "libreoffice");
105 }
106
107@@ -829,7 +831,7 @@
108 return;
109 }
110
111- if (exec_string_should_be_processed (self, exec))
112+ if (exec_string_should_be_processed (exec))
113 {
114 /**
115 * Set of nasty hacks which should be removed some day. We wish to keep the full exec
116@@ -939,7 +941,7 @@
117 gchar **parts = g_strsplit (line, "\t", 3);
118 exec = parts[1];
119
120- if (exec_string_should_be_processed (self, exec))
121+ if (exec_string_should_be_processed (exec))
122 {
123 char *tmp = trim_exec_string (self, exec);
124 g_free (parts[1]);
125@@ -1377,6 +1379,9 @@
126 {
127 const char *class_name = bamf_legacy_window_get_class_name (window);
128
129+ if (!class_name)
130+ return FALSE;
131+
132 return (g_str_has_prefix (class_name, "LibreOffice") ||
133 g_str_has_prefix (class_name, "libreoffice") ||
134 g_str_has_prefix (class_name, "OpenOffice") ||
135@@ -1543,17 +1548,20 @@
136
137 gboolean valid_app = FALSE;
138
139- if (g_strcmp0 (window_class, "Google-chrome") == 0 &&
140- g_strcmp0 (instance_name, "google-chrome") != 0 &&
141- !g_str_has_prefix (instance_name, "Google-chrome"))
142- {
143- valid_app = TRUE;
144- }
145- else if (g_strcmp0 (window_class, "Chromium-browser") == 0 &&
146- g_strcmp0 (instance_name, "chromium-browser") != 0 &&
147- !g_str_has_prefix (instance_name, "Chromium-browser"))
148- {
149- valid_app = TRUE;
150+ if (instance_name && window_class)
151+ {
152+ if (g_strcmp0 (window_class, "Google-chrome") == 0 &&
153+ g_strcmp0 (instance_name, "google-chrome") != 0 &&
154+ !g_str_has_prefix (instance_name, "Google-chrome"))
155+ {
156+ valid_app = TRUE;
157+ }
158+ else if (g_strcmp0 (window_class, "Chromium-browser") == 0 &&
159+ g_strcmp0 (instance_name, "chromium-browser") != 0 &&
160+ !g_str_has_prefix (instance_name, "Chromium-browser"))
161+ {
162+ valid_app = TRUE;
163+ }
164 }
165
166 return valid_app;
167@@ -1620,36 +1628,50 @@
168
169 static GList *
170 bamf_matcher_possible_applications_for_window (BamfMatcher *self,
171- BamfWindow *bamf_window)
172+ BamfWindow *bamf_window,
173+ const char **target_class_out)
174 {
175 BamfMatcherPrivate *priv;
176 BamfLegacyWindow *window;
177 GList *desktop_files = NULL, *l;
178 char *desktop_file = NULL;
179- char *desktop_class = NULL;
180+ const char *desktop_class = NULL;
181+ const char *class_name = NULL;
182+ const char *instance_name = NULL;
183+ const char *target_class = NULL;
184+ gboolean filter_by_wmclass = FALSE;
185
186 g_return_val_if_fail (BAMF_IS_WINDOW (bamf_window), NULL);
187 g_return_val_if_fail (BAMF_IS_MATCHER (self), NULL);
188
189 priv = self->priv;
190 window = bamf_window_get_window (bamf_window);
191-
192 desktop_file = get_window_hint (window, _NET_WM_DESKTOP_FILE);
193-
194- const char *class_name = bamf_legacy_window_get_class_name (window);
195- const char *instance_name = bamf_legacy_window_get_class_instance_name (window);
196- gboolean known_desktop_class = bamf_matcher_has_instance_class_desktop_file (self, instance_name);
197-
198- if (!known_desktop_class)
199+ class_name = bamf_legacy_window_get_class_name (window);
200+ instance_name = bamf_legacy_window_get_class_instance_name (window);
201+
202+ target_class = instance_name;
203+ filter_by_wmclass = bamf_matcher_has_instance_class_desktop_file (self, target_class);
204+
205+ if (!filter_by_wmclass)
206 {
207- known_desktop_class = is_web_app_window (self, window);
208+ if (is_web_app_window (self, window))
209+ {
210+ // This ensures that a new application is created even for unknown webapps
211+ filter_by_wmclass = TRUE;
212+ }
213+ else
214+ {
215+ target_class = class_name;
216+ filter_by_wmclass = bamf_matcher_has_instance_class_desktop_file (self, target_class);
217+ }
218 }
219
220 if (desktop_file)
221 {
222- desktop_class = g_hash_table_lookup (priv->desktop_class_table, desktop_file);
223+ desktop_class = bamf_matcher_get_desktop_file_class (self, desktop_file);
224
225- if (!known_desktop_class || g_strcmp0 (desktop_class, instance_name) == 0)
226+ if ((!filter_by_wmclass && !desktop_class) || g_strcmp0 (desktop_class, target_class) == 0)
227 {
228 desktop_files = g_list_prepend (desktop_files, desktop_file);
229 }
230@@ -1675,9 +1697,9 @@
231
232 if (desktop_file)
233 {
234- desktop_class = g_hash_table_lookup (priv->desktop_class_table, desktop_file);
235+ desktop_class = bamf_matcher_get_desktop_file_class (self, desktop_file);
236
237- if (!known_desktop_class || g_strcmp0 (desktop_class, instance_name) == 0)
238+ if ((!filter_by_wmclass && !desktop_class) || g_strcmp0 (desktop_class, target_class) == 0)
239 {
240 if (!g_list_find_custom (desktop_files, desktop_file,
241 (GCompareFunc) g_strcmp0))
242@@ -1708,10 +1730,10 @@
243 {
244 gboolean append = FALSE;
245
246- if (instance_name)
247+ if (target_class)
248 {
249- desktop_class = g_hash_table_lookup (priv->desktop_class_table, desktop_file);
250- if (!known_desktop_class || g_strcmp0 (desktop_class, instance_name) == 0)
251+ desktop_class = bamf_matcher_get_desktop_file_class (self, desktop_file);
252+ if ((!filter_by_wmclass && !desktop_class) || g_strcmp0 (desktop_class, target_class) == 0)
253 {
254 append = TRUE;
255 }
256@@ -1753,34 +1775,40 @@
257 g_list_free (pid_list);
258 }
259
260- if (!desktop_files && known_desktop_class)
261- {
262- desktop_files = bamf_matcher_get_class_matching_desktop_files (self, instance_name);
263+ if (!desktop_files && filter_by_wmclass)
264+ {
265+ desktop_files = bamf_matcher_get_class_matching_desktop_files (self, target_class);
266+ }
267+
268+ if (target_class_out)
269+ {
270+ *target_class_out = target_class;
271 }
272
273 return desktop_files;
274 }
275
276-static void
277-bamf_matcher_setup_window_state (BamfMatcher *self,
278- BamfWindow *bamf_window)
279+static BamfApplication *
280+bamf_matcher_get_application_for_window (BamfMatcher *self,
281+ BamfWindow *bamf_window,
282+ gboolean *new_application)
283 {
284 GList *possible_apps, *l;
285 BamfLegacyWindow *window;
286- const gchar *app_class;
287+ const gchar *win_class_name;
288+ const gchar *target_class = NULL;
289+ const gchar *app_class = NULL;
290 const gchar *app_desktop = NULL;
291 BamfApplication *app = NULL, *best = NULL;
292
293- g_return_if_fail (BAMF_IS_MATCHER (self));
294- g_return_if_fail (BAMF_IS_WINDOW (bamf_window));
295+ g_return_val_if_fail (BAMF_IS_MATCHER (self), NULL);
296+ g_return_val_if_fail (BAMF_IS_WINDOW (bamf_window), NULL);
297
298 window = bamf_window_get_window (bamf_window);
299-
300- possible_apps = bamf_matcher_possible_applications_for_window (self, bamf_window);
301- const char *win_instance = bamf_legacy_window_get_class_instance_name (window);
302- const char *win_class_name = bamf_legacy_window_get_class_name (window);
303-
304- app_class = win_instance;
305+ win_class_name = bamf_legacy_window_get_class_name (window);
306+
307+ possible_apps = bamf_matcher_possible_applications_for_window (self, bamf_window, &target_class);
308+ app_class = target_class;
309
310 /* Loop over every possible desktop file that could match the window, and try
311 * to reuse an already-opened window that uses it.
312@@ -1799,7 +1827,7 @@
313 const gchar *app_desktop_class;
314 app_desktop_class = bamf_application_get_wmclass (app);
315
316- if (win_instance && app_desktop_class && strcasecmp (win_instance, app_desktop_class) == 0)
317+ if (target_class && app_desktop_class && strcasecmp (target_class, app_desktop_class) == 0)
318 {
319 best = app;
320 break;
321@@ -1829,7 +1857,7 @@
322 const gchar *best_desktop_class;
323
324 best_app_class = bamf_application_get_wmclass (best);
325- best_desktop_class = g_hash_table_lookup (self->priv->desktop_class_table, best_desktop);
326+ best_desktop_class = bamf_matcher_get_desktop_file_class (self, best_desktop);
327
328 /* We compare the two classes using their "distance" from the
329 * desidered class value */
330@@ -1867,7 +1895,7 @@
331
332 if (bamf_application_contains_similar_to_window (app, bamf_window))
333 {
334- if (win_instance && g_strcmp0 (win_instance, app_desktop_class) == 0)
335+ if (target_class && g_strcmp0 (target_class, app_desktop_class) == 0)
336 {
337 best = app;
338 break;
339@@ -1896,12 +1924,19 @@
340 }
341
342 bamf_application_set_wmclass (best, app_class);
343- bamf_matcher_register_view_stealing_ref (self, BAMF_VIEW (best));
344- }
345
346- bamf_view_add_child (BAMF_VIEW (best), BAMF_VIEW (bamf_window));
347+ if (new_application)
348+ *new_application = TRUE;
349+ }
350+ else
351+ {
352+ if (new_application)
353+ *new_application = FALSE;
354+ }
355
356 g_list_free_full (possible_apps, g_free);
357+
358+ return best;
359 }
360
361 /* Ensures that the window hint is set if a registered pid matches, and that set window hints
362@@ -1972,6 +2007,7 @@
363 handle_raw_window (BamfMatcher *self, BamfLegacyWindow *window)
364 {
365 BamfWindow *bamfwindow;
366+ BamfApplication *bamfapplication;
367
368 g_return_if_fail (BAMF_IS_MATCHER (self));
369 g_return_if_fail (BAMF_IS_LEGACY_WINDOW (window));
370@@ -1989,7 +2025,15 @@
371 bamfwindow = bamf_window_new (window);
372 bamf_matcher_register_view_stealing_ref (self, BAMF_VIEW (bamfwindow));
373
374- bamf_matcher_setup_window_state (self, bamfwindow);
375+ gboolean new_app = FALSE;
376+ bamfapplication = bamf_matcher_get_application_for_window (self, bamfwindow, &new_app);
377+
378+ if (new_app)
379+ {
380+ bamf_matcher_register_view_stealing_ref (self, BAMF_VIEW (bamfapplication));
381+ }
382+
383+ bamf_view_add_child (BAMF_VIEW (bamfapplication), BAMF_VIEW (bamfwindow));
384 }
385
386 static void
387@@ -2243,6 +2287,15 @@
388 }
389 }
390
391+const char *
392+bamf_matcher_get_desktop_file_class (BamfMatcher * self, const char * desktop_file)
393+{
394+ g_return_val_if_fail (BAMF_IS_MATCHER (self), NULL);
395+ g_return_val_if_fail (desktop_file, NULL);
396+
397+ return g_hash_table_lookup (self->priv->desktop_class_table, desktop_file);
398+}
399+
400 static int
401 x_error_handler (Display *display, XErrorEvent *event)
402 {
403@@ -2347,7 +2400,6 @@
404 return (idx_a < idx_b) ? -1 : 1;
405 }
406
407-
408 GVariant *
409 bamf_matcher_get_window_stack_for_monitor (BamfMatcher *matcher, gint monitor)
410 {
411@@ -2515,8 +2567,8 @@
412 if (g_list_find_custom (priv->favorites, fav, (GCompareFunc) g_strcmp0))
413 continue;
414
415+ bamf_matcher_load_desktop_file (matcher, fav);
416 priv->favorites = g_list_prepend (priv->favorites, g_strdup (fav));
417- bamf_matcher_load_desktop_file (matcher, fav);
418 }
419
420 g_signal_emit (matcher, matcher_signals[FAVORITES_CHANGED], 0);
421
422=== modified file 'src/bamf-matcher.h'
423--- src/bamf-matcher.h 2012-01-21 00:29:55 +0000
424+++ src/bamf-matcher.h 2012-05-22 16:24:22 +0000
425@@ -74,6 +74,9 @@
426 const char *application,
427 gint pid);
428
429+const char * bamf_matcher_get_desktop_file_class (BamfMatcher * self,
430+ const char * desktop_file);
431+
432 const char * bamf_matcher_get_active_application (BamfMatcher *matcher);
433
434 const char * bamf_matcher_get_active_window (BamfMatcher *matcher);

Subscribers

People subscribed via source and target branches