Merge lp:~3v1n0/bamf/libreoffice-fixes into lp:bamf/0.4

Proposed by Marco Trevisan (Treviño)
Status: Merged
Approved by: Mikkel Kamstrup Erlandsen
Approved revision: 443
Merged at revision: 424
Proposed branch: lp:~3v1n0/bamf/libreoffice-fixes
Merge into: lp:bamf/0.4
Diff against target: 805 lines (+327/-147)
8 files modified
configure.in (+1/-1)
src/bamf-application.c (+15/-2)
src/bamf-legacy-screen.c (+31/-0)
src/bamf-legacy-screen.h (+2/-0)
src/bamf-legacy-window.c (+35/-7)
src/bamf-legacy-window.h (+2/-0)
src/bamf-matcher.c (+234/-136)
src/bamf-view.c (+7/-1)
To merge this branch: bzr merge lp:~3v1n0/bamf/libreoffice-fixes
Reviewer Review Type Date Requested Status
Mikkel Kamstrup Erlandsen (community) Approve
Review via email: mp+85395@code.launchpad.net

Commit message

Fixed LibreOffice and OpenOffice compatibility, remapping windows to their real type

Description of the change

When a window can be mapped as a LibreOffice / OpenOffice application we look for the right hint for the given window, we set that hint by default (if valid) and we connect to the window's name-changed event.
So, every time the window name changes, we check again for the window type and if it has changed (i.e. we moved from writer to start-center), then we simulate a window open/close event that cause the window to be re-mapped to
the proper application.
This works very well and allows to change the application type on run-time.

Also, every recognized libreoffice window that doesn't match any main application, is now considered as a "Standard" libreoffice application window, using the libreoffice-startcenter icon.
This allows to correctly match not only the start center, but also dialog windows such as the restore window that shows up after a crash.
I also tried to introduce matching based on window class names (using libreoffice-writer, libreoffice-calc ... values), but since these parameters get updated only after the window name change, this check could be confusing (also if theoretically more secure).

The splash screen and the toolbars are now ignored, and so don't respect the rules above.

I've also included some optimizations, fixes (memleaks) and code cleanup.

To post a comment you must log in.
Revision history for this message
Mikkel Kamstrup Erlandsen (kamstrup) wrote :

Firstly - I LOVE you for getting rid of all the 'key = g_new (gint, 1);' that just gross in so many ways :-) Now for some comments:

8 - icon = g_icon_to_string (gicon);
9 +
10 + if (gicon)
11 + icon = g_icon_to_string (gicon);

The function you're updating here, bamf_application_setup_icon_and_name(), seems to leak self->priv->icon right at the end if it's set before we assign it. Can you plug that while you're here?

30 void
31 +bamf_legacy_screen_inject_window (BamfLegacyScreen *self, guint xid)

It's not totally clear to me what this function is intended to do. Can you add a short docstring? (I assume most ppl wont bother to dig out of the revision history like me ;-))

94 +void
95 +bamf_legacy_window_reopen (BamfLegacyWindow *self)

Same as the last new function :-)

101 + g_object_weak_ref (G_OBJECT (self), (GWeakNotify) handle_destroy_notify,
102 + GUINT_TO_POINTER (xid));

It's not very clear what the magic behind this weak ref is, could you add an explanatory comment?

373 + g_list_free_full (possible_apps, g_free);

The introduction of g_list_free_full() is nice, but requires glib >=2.28. Please add that check to configure.in.

423 + if (!g_hash_table_lookup (registered_pids, key))
424 + {
425 + g_hash_table_insert (registered_pids, key, g_strdup (window_hint));
426 + }

Only updating if we don't already know the pid seems like it could cause things to go askew? If that's not the case I think this logic requires a comment in the code.

628 static void
629 +bamf_matcher_dispose (GObject *object)

This function does not look like it's safe to run N times on the same object. That is the contract of dispose(). Fx. looking at this block makes me suspicious:

642 + g_array_free (priv->bad_prefixes, TRUE);
643 + g_array_free (priv->known_pids, TRUE);
644 + g_hash_table_destroy (priv->desktop_id_table);
645 + g_hash_table_destroy (priv->desktop_file_table);
646 + g_hash_table_destroy (priv->desktop_class_table);
647 + g_hash_table_destroy (priv->registered_pids);

You must add NULL-ification and NULL-checking on all members. If you don't want that override finalize() instead which is guaranteed to run only once.

695 + GObject *old_object = dbus_g_connection_lookup_g_object (bus, path);
696 + if (G_IS_OBJECT (old_object))
697 + {
698 + dbus_g_connection_unregister_g_object (bus, old_object);
699 + }

The commit message for this chunk mentions that you log a g_critical()when you replace an object. I don't see that critical being logged - is that intentional?

review: Needs Fixing
lp:~3v1n0/bamf/libreoffice-fixes updated
436. By Marco Trevisan (Treviño)

BamfApplication: don't leak the icon string

437. By Marco Trevisan (Treviño)

Configure.in: set glib-2.0 >= 2.28 to support g_list_free_full

438. By Marco Trevisan (Treviño)

BamfMatcher: use finalize function, instead of dispose.

439. By Marco Trevisan (Treviño)

BamfView: emit a g_critical message when unregistering a DBus object

440. By Marco Trevisan (Treviño)

BamfLegacyScreen: added docs to bamf_legacy_screen_inject_window

Revision history for this message
Marco Trevisan (Treviño) (3v1n0) wrote :

> Firstly - I LOVE you for getting rid of all the 'key = g_new (gint, 1);' that
> just gross in so many ways :-)

Yes, I'm sure that there are also some other leaks around, but I've not read everything yet. :)

Now for some comments:

> The function you're updating here, bamf_application_setup_icon_and_name(),
> seems to leak self->priv->icon right at the end if it's set before we assign
> it. Can you plug that while you're here?

Done. Free'd also on dispose.

> 30 void
> 31 +bamf_legacy_screen_inject_window (BamfLegacyScreen *self, guint xid)
>
> It's not totally clear to me what this function is intended to do. Can you add
> a short docstring? (I assume most ppl wont bother to dig out of the revision
> history like me ;-))

Done.

> 94 +void
> 95 +bamf_legacy_window_reopen (BamfLegacyWindow *self)
>
> Same as the last new function :-)

Done.

> 101 + g_object_weak_ref (G_OBJECT (self), (GWeakNotify)
> handle_destroy_notify,
> 102 + GUINT_TO_POINTER (xid));
>
> It's not very clear what the magic behind this weak ref is, could you add an
> explanatory comment?

Ok.

> 373 + g_list_free_full (possible_apps, g_free);
>
> The introduction of g_list_free_full() is nice, but requires glib >=2.28.
> Please add that check to configure.in.

Done.

> 423 + if (!g_hash_table_lookup (registered_pids, key))
> 424 + {
> 425 + g_hash_table_insert (registered_pids, key, g_strdup (window_hint));
> 426 + }
>
> Only updating if we don't already know the pid seems like it could cause
> things to go askew? If that's not the case I think this logic requires a
> comment in the code.

Well, this code was already there and I just kept the old behavior alive. However it seems to work well, also because generally a pid is always connected to just one application, except particular cases like this one (libreoffice or chromium).
However, I'll study more on this and eventually I'll change this code.

> 628 static void
> 629 +bamf_matcher_dispose (GObject *object)
>
> This function does not look like it's safe to run N times on the same object.
> That is the contract of dispose(). Fx.

Right, moving to finalize().

> The commit message for this chunk mentions that you log a g_critical()when you
> replace an object. I don't see that critical being logged - is that
> intentional?

Ehehe... Really it was there, but I don't know why I've not committed it.
Re-added! ;)

lp:~3v1n0/bamf/libreoffice-fixes updated
441. By Marco Trevisan (Treviño)

BamfLegacyWindow: added docs to bamf_legacy_window_reopen

442. By Marco Trevisan (Treviño)

BamfMatcher: correctly match the libreoffice transient windows.

We'll use the class name for matching them. This allows to be even more precise.

Revision history for this message
Mikkel Kamstrup Erlandsen (kamstrup) wrote :

Ok, looking good now. Awesome work! Just one line to fix before I can approve this:

773 + object_class->dispose = bamf_matcher_finalize;

You mean

 + object_class->finalize = bamf_matcher_finalize;

:-)

review: Needs Fixing
lp:~3v1n0/bamf/libreoffice-fixes updated
443. By Marco Trevisan (Treviño)

BamfMatcher: fixing typo s/dispose/finalize/

Revision history for this message
Mikkel Kamstrup Erlandsen (kamstrup) wrote :

I am happy! :-D

review: Approve

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
=== modified file 'configure.in'
--- configure.in 2011-11-28 10:17:05 +0000
+++ configure.in 2011-12-15 11:35:15 +0000
@@ -56,7 +56,7 @@
56#56#
57# glib57# glib
58#58#
59PKG_CHECK_MODULES(GLIB, glib-2.0 >= 2.16.0 gio-2.0 gio-unix-2.0)59PKG_CHECK_MODULES(GLIB, glib-2.0 >= 2.28.0 gio-2.0 gio-unix-2.0)
6060
61#61#
62# dbus62# dbus
6363
=== modified file 'src/bamf-application.c'
--- src/bamf-application.c 2011-08-30 20:47:15 +0000
+++ src/bamf-application.c 2011-12-15 11:35:15 +0000
@@ -145,7 +145,9 @@
145 gicon = g_app_info_get_icon (G_APP_INFO (desktop));145 gicon = g_app_info_get_icon (G_APP_INFO (desktop));
146146
147 name = g_strdup (g_app_info_get_display_name (G_APP_INFO (desktop)));147 name = g_strdup (g_app_info_get_display_name (G_APP_INFO (desktop)));
148 icon = g_icon_to_string (gicon);148
149 if (gicon)
150 icon = g_icon_to_string (gicon);
149151
150 if (g_key_file_has_key(keyfile, G_KEY_FILE_DESKTOP_GROUP, STUB_KEY, NULL)) {152 if (g_key_file_has_key(keyfile, G_KEY_FILE_DESKTOP_GROUP, STUB_KEY, NULL)) {
151 /* This will error to return false, which is okay as it seems153 /* This will error to return false, which is okay as it seems
@@ -227,7 +229,12 @@
227 }229 }
228230
229 if (icon)231 if (icon)
230 self->priv->icon = icon;232 {
233 if (self->priv->icon)
234 g_free (self->priv->icon);
235
236 self->priv->icon = icon;
237 }
231238
232 if (name)239 if (name)
233 bamf_view_set_name (BAMF_VIEW (self), name);240 bamf_view_set_name (BAMF_VIEW (self), name);
@@ -611,6 +618,12 @@
611 priv->app_type = NULL;618 priv->app_type = NULL;
612 }619 }
613620
621 if (priv->icon)
622 {
623 g_free (priv->icon);
624 priv->icon = NULL;
625 }
626
614 if (priv->wmclass)627 if (priv->wmclass)
615 {628 {
616 g_free (priv->wmclass);629 g_free (priv->wmclass);
617630
=== modified file 'src/bamf-legacy-screen.c'
--- src/bamf-legacy-screen.c 2011-08-01 23:25:01 +0000
+++ src/bamf-legacy-screen.c 2011-12-15 11:35:15 +0000
@@ -160,6 +160,7 @@
160handle_window_opened (WnckScreen *screen, WnckWindow *window, BamfLegacyScreen *legacy)160handle_window_opened (WnckScreen *screen, WnckWindow *window, BamfLegacyScreen *legacy)
161{161{
162 BamfLegacyWindow *legacy_window;162 BamfLegacyWindow *legacy_window;
163 g_return_if_fail (WNCK_IS_WINDOW (window));
163164
164 legacy_window = bamf_legacy_window_new (window);165 legacy_window = bamf_legacy_window_new (window);
165166
@@ -171,6 +172,36 @@
171 g_signal_emit (legacy, legacy_screen_signals[WINDOW_OPENED], 0, legacy_window);172 g_signal_emit (legacy, legacy_screen_signals[WINDOW_OPENED], 0, legacy_window);
172}173}
173174
175/* This function allows to push into the screen a window by its xid.
176 * If the window is already known, it's just ignored, otherwise it gets added
177 * to the windows list. The BamfLegacyScreen should automatically update its
178 * windows list when they are added/removed from the screen, but if a child
179 * BamfLegacyWindow is closed, then it could be possible to re-add it. */
180void
181bamf_legacy_screen_inject_window (BamfLegacyScreen *self, guint xid)
182{
183 g_return_if_fail (BAMF_IS_LEGACY_SCREEN (self));
184 BamfLegacyWindow *window;
185 GList *l;
186
187 for (l = self->priv->windows; l; l = l->next)
188 {
189 window = l->data;
190
191 if (bamf_legacy_window_get_xid (window) == xid)
192 {
193 return;
194 }
195 }
196
197 WnckWindow *legacy_window = wnck_window_get(xid);
198
199 if (WNCK_IS_WINDOW (legacy_window))
200 {
201 handle_window_opened(NULL, legacy_window, self);
202 }
203}
204
174void205void
175bamf_legacy_screen_set_state_file (BamfLegacyScreen *self,206bamf_legacy_screen_set_state_file (BamfLegacyScreen *self,
176 const char *file)207 const char *file)
177208
=== modified file 'src/bamf-legacy-screen.h'
--- src/bamf-legacy-screen.h 2010-05-25 13:47:38 +0000
+++ src/bamf-legacy-screen.h 2011-12-15 11:35:15 +0000
@@ -67,4 +67,6 @@
6767
68BamfLegacyScreen * bamf_legacy_screen_get_default (void);68BamfLegacyScreen * bamf_legacy_screen_get_default (void);
6969
70void bamf_legacy_screen_inject_window (BamfLegacyScreen *screen, guint xid);
71
70#endif72#endif
7173
=== modified file 'src/bamf-legacy-window.c'
--- src/bamf-legacy-window.c 2011-11-29 08:04:22 +0000
+++ src/bamf-legacy-window.c 2011-12-15 11:35:15 +0000
@@ -328,13 +328,41 @@
328{328{
329 g_return_if_fail (BAMF_IS_LEGACY_WINDOW (self));329 g_return_if_fail (BAMF_IS_LEGACY_WINDOW (self));
330 g_return_if_fail (WNCK_IS_WINDOW (window));330 g_return_if_fail (WNCK_IS_WINDOW (window));
331 331
332 if (self->priv->legacy_window == window)
333 {
334 self->priv->is_closed = TRUE;
335 g_signal_emit (self, legacy_window_signals[CLOSED], 0);
336 }
337}
338
339static void
340handle_destroy_notify (gpointer *data, BamfLegacyWindow *self_was_here)
341{
342 BamfLegacyScreen *screen = bamf_legacy_screen_get_default ();
343 bamf_legacy_screen_inject_window (screen, GPOINTER_TO_UINT (data));
344}
345
346/* This utility function allows to set a BamfLegacyWindow as closed, notifying
347 * all its owners, and to reopen it once the current window has been destroyed.
348 * This allows to remap particular windows to different applications. */
349void
350bamf_legacy_window_reopen (BamfLegacyWindow *self)
351{
352 g_return_if_fail (BAMF_IS_LEGACY_WINDOW (self));
353 g_return_if_fail (WNCK_IS_WINDOW (self->priv->legacy_window));
354
355 guint xid = bamf_legacy_window_get_xid (self);
356
357 /* Adding a weak ref to this object, causes to get notified after the object
358 * destruction, so once this BamfLegacyWindow has been closed and drestroyed
359 * the handle_destroy_notify() function will be called, and that will
360 * provide to iniject another window like this one to the BamfLegacyScreen */
361 g_object_weak_ref (G_OBJECT (self), (GWeakNotify) handle_destroy_notify,
362 GUINT_TO_POINTER (xid));
363
332 self->priv->is_closed = TRUE;364 self->priv->is_closed = TRUE;
333365 g_signal_emit (self, legacy_window_signals[CLOSED], 0);
334 if (window == self->priv->legacy_window)
335 {
336 g_signal_emit (self, legacy_window_signals[CLOSED], 0);
337 }
338}366}
339367
340static void368static void
@@ -381,7 +409,7 @@
381 screen = wnck_screen_get_default ();409 screen = wnck_screen_get_default ();
382410
383 priv->closed_id = g_signal_connect (G_OBJECT (screen), "window-closed",411 priv->closed_id = g_signal_connect (G_OBJECT (screen), "window-closed",
384 (GCallback) handle_window_closed, self);412 (GCallback) handle_window_closed, self);
385}413}
386414
387static void415static void
388416
=== modified file 'src/bamf-legacy-window.h'
--- src/bamf-legacy-window.h 2011-09-26 11:44:10 +0000
+++ src/bamf-legacy-window.h 2011-12-15 11:35:15 +0000
@@ -112,6 +112,8 @@
112112
113BamfLegacyWindow * bamf_legacy_window_get_transient (BamfLegacyWindow *self);113BamfLegacyWindow * bamf_legacy_window_get_transient (BamfLegacyWindow *self);
114114
115void bamf_legacy_window_reopen (BamfLegacyWindow *self);
116
115BamfLegacyWindow * bamf_legacy_window_new (WnckWindow *legacy_window);117BamfLegacyWindow * bamf_legacy_window_new (WnckWindow *legacy_window);
116118
117#endif119#endif
118120
=== modified file 'src/bamf-matcher.c'
--- src/bamf-matcher.c 2011-09-29 20:31:13 +0000
+++ src/bamf-matcher.c 2011-12-15 11:35:15 +0000
@@ -14,6 +14,7 @@
14 * along with this program. If not, see <http://www.gnu.org/licenses/>.14 * along with this program. If not, see <http://www.gnu.org/licenses/>.
15 *15 *
16 * Authored by: Jason Smith <jason.smith@canonical.com>16 * Authored by: Jason Smith <jason.smith@canonical.com>
17 * Marco Trevisan (Treviño) <3v1n0@ubuntu.com>
17 *18 *
18 */19 */
1920
@@ -65,7 +66,6 @@
65 GHashTable * desktop_id_table;66 GHashTable * desktop_id_table;
66 GHashTable * desktop_file_table;67 GHashTable * desktop_file_table;
67 GHashTable * desktop_class_table;68 GHashTable * desktop_class_table;
68 GHashTable * exec_list;
69 GHashTable * registered_pids;69 GHashTable * registered_pids;
70 GList * views;70 GList * views;
71 GList * monitors;71 GList * monitors;
@@ -135,12 +135,12 @@
135 }135 }
136}136}
137137
138static void bamf_matcher_unregister_view (BamfMatcher *self, BamfView *view);138static void bamf_matcher_unregister_view (BamfMatcher *self, BamfView *view, gboolean unref);
139139
140static void140static void
141on_view_closed (BamfView *view, BamfMatcher *self)141on_view_closed (BamfView *view, BamfMatcher *self)
142{142{
143 bamf_matcher_unregister_view (self, view);143 bamf_matcher_unregister_view (self, view, TRUE);
144}144}
145145
146static void146static void
@@ -168,7 +168,7 @@
168}168}
169169
170static void170static void
171bamf_matcher_unregister_view (BamfMatcher *self, BamfView *view)171bamf_matcher_unregister_view (BamfMatcher *self, BamfView *view, gboolean unref)
172{172{
173 const char * path;173 const char * path;
174 char * type;174 char * type;
@@ -181,8 +181,11 @@
181 g_signal_handlers_disconnect_by_func (G_OBJECT (view), on_view_closed, self);181 g_signal_handlers_disconnect_by_func (G_OBJECT (view), on_view_closed, self);
182 g_signal_handlers_disconnect_by_func (G_OBJECT (view), on_view_active_changed, self);182 g_signal_handlers_disconnect_by_func (G_OBJECT (view), on_view_active_changed, self);
183183
184 self->priv->views = g_list_remove (self->priv->views, view);184 if (unref)
185 g_object_unref (view);185 {
186 self->priv->views = g_list_remove (self->priv->views, view);
187 g_object_unref (view);
188 }
186189
187 g_free (type);190 g_free (type);
188}191}
@@ -191,7 +194,7 @@
191get_open_office_window_hint (BamfMatcher * self, BamfLegacyWindow * window)194get_open_office_window_hint (BamfMatcher * self, BamfLegacyWindow * window)
192{195{
193 const gchar *name;196 const gchar *name;
194 char *exec;197 char *exec = NULL;
195 GHashTable *desktopFileTable;198 GHashTable *desktopFileTable;
196 GList *list;199 GList *list;
197200
@@ -199,18 +202,44 @@
199 g_return_val_if_fail (BAMF_IS_LEGACY_WINDOW (window), NULL);202 g_return_val_if_fail (BAMF_IS_LEGACY_WINDOW (window), NULL);
200203
201 name = bamf_legacy_window_get_name (window);204 name = bamf_legacy_window_get_name (window);
205 const gchar *class = bamf_legacy_window_get_class_name (window);
206 BamfWindowType type = bamf_legacy_window_get_window_type (window);
202207
203 if (name == NULL)208 if (name == NULL && class == NULL)
204 return NULL;209 return NULL;
205210
206 if (g_str_has_suffix (name, "OpenOffice.org Writer"))211 if (g_str_has_suffix (name, "LibreOffice Writer"))
212 {
213 exec = "libreoffice -writer %U";
214 }
215 else if (g_str_has_suffix (name, "LibreOffice Calc"))
216 {
217 exec = "libreoffice -calc %U";
218 }
219 else if (g_str_has_suffix (name, "LibreOffice Impress"))
220 {
221 exec = "libreoffice -impress %U";
222 }
223 else if (g_str_has_suffix (name, "LibreOffice Math"))
224 {
225 exec = "libreoffice -math %U";
226 }
227 else if (g_str_has_suffix (name, "LibreOffice Draw"))
228 {
229 exec = "libreoffice -draw %U";
230 }
231 else if (g_strcmp0 (class, "libreoffice-startcenter") == 0)
232 {
233 exec = "libreoffice %U";
234 }
235 else if (g_strcmp0 (name, "LibreOffice") == 0 && type == BAMF_WINDOW_NORMAL)
236 {
237 exec = "libreoffice %U";
238 }
239 else if (g_str_has_suffix (name, "OpenOffice.org Writer"))
207 {240 {
208 exec = "ooffice -writer %F";241 exec = "ooffice -writer %F";
209 }242 }
210 else if (g_str_has_suffix (name, "OpenOffice.org Math"))
211 {
212 exec = "ooffice -math %F";
213 }
214 else if (g_str_has_suffix (name, "OpenOffice.org Calc"))243 else if (g_str_has_suffix (name, "OpenOffice.org Calc"))
215 {244 {
216 exec = "ooffice -calc %F";245 exec = "ooffice -calc %F";
@@ -219,41 +248,63 @@
219 {248 {
220 exec = "ooffice -impress %F";249 exec = "ooffice -impress %F";
221 }250 }
251 else if (g_str_has_suffix (name, "OpenOffice.org Math"))
252 {
253 exec = "ooffice -math %F";
254 }
222 else if (g_str_has_suffix (name, "OpenOffice.org Draw"))255 else if (g_str_has_suffix (name, "OpenOffice.org Draw"))
223 {256 {
224 exec = "ooffice -draw %F";257 exec = "ooffice -draw %F";
225 }258 }
226 else if (g_str_has_suffix (name, "LibreOffice Writer"))259 else if (g_strcmp0 (name, "OpenOffice.org") == 0 && type == BAMF_WINDOW_NORMAL)
227 {260 {
228 exec = "libreoffice -writer %U";261 exec = "ooffice %F";
229 }
230 else if (g_str_has_suffix (name, "LibreOffice Math"))
231 {
232 exec = "libreoffice -math %U";
233 }
234 else if (g_str_has_suffix (name, "LibreOffice Calc"))
235 {
236 exec = "libreoffice -calc %U";
237 }
238 else if (g_str_has_suffix (name, "LibreOffice Impress"))
239 {
240 exec = "libreoffice -impress %U";
241 }
242 else if (g_str_has_suffix (name, "LibreOffice Draw"))
243 {
244 exec = "libreoffice -draw %U";
245 }262 }
246 else263 else
247 {264 {
248 return NULL;265 if (type != BAMF_WINDOW_NORMAL || bamf_legacy_window_get_transient (window))
266 {
267 /* Child windows can generally easily be recognized by their class */
268 if (g_strcmp0 (class, "libreoffice-writer") == 0)
269 {
270 exec = "libreoffice -writer %U";
271 }
272 else if (g_strcmp0 (class, "libreoffice-calc") == 0)
273 {
274 exec = "libreoffice -calc %U";
275 }
276 else if (g_strcmp0 (class, "libreoffice-impress") == 0)
277 {
278 exec = "libreoffice -impress %U";
279 }
280 else if (g_strcmp0 (class, "libreoffice-math") == 0)
281 {
282 exec = "libreoffice -math %U";
283 }
284 else if (g_strcmp0 (class, "libreoffice-draw") == 0)
285 {
286 exec = "libreoffice -draw %U";
287 }
288 }
289
290 if (!exec)
291 {
292 /* By default fallback to the main launcher */
293 if (g_str_has_prefix (class, "OpenOffice"))
294 {
295 exec = "ooffice %F";
296 }
297 else
298 {
299 exec = "libreoffice %U";
300 }
301 }
249 }302 }
250303
251 desktopFileTable = self->priv->desktop_file_table;304 desktopFileTable = self->priv->desktop_file_table;
252 list = g_hash_table_lookup (desktopFileTable, exec);305 list = g_hash_table_lookup (desktopFileTable, exec);
253306
254 g_return_val_if_fail (list, NULL);307 return (list ? (char *) list->data : NULL);
255
256 return (char *) list->data;
257}308}
258309
259/* Attempts to return the binary name for a particular execution string */310/* Attempts to return the binary name for a particular execution string */
@@ -266,7 +317,7 @@
266 gboolean regexFail;317 gboolean regexFail;
267 GRegex *regex;318 GRegex *regex;
268319
269 g_return_val_if_fail (execString && strlen (execString) > 0, g_strdup (execString));320 g_return_val_if_fail ((execString && execString[0] != '\0'), g_strdup (execString));
270321
271 exec = g_utf8_casefold (execString, -1);322 exec = g_utf8_casefold (execString, -1);
272 parts = g_strsplit (exec, " ", 0);323 parts = g_strsplit (exec, " ", 0);
@@ -996,7 +1047,7 @@
996 self->priv->desktop_id_table,1047 self->priv->desktop_id_table,
997 self->priv->desktop_class_table);1048 self->priv->desktop_class_table);
998 1049
999 g_list_free_full (dirs, (GDestroyNotify) g_free);1050 g_list_free_full (dirs, g_free);
1000 }1051 }
1001 }1052 }
1002 else if (filetype != G_FILE_TYPE_UNKNOWN)1053 else if (filetype != G_FILE_TYPE_UNKNOWN)
@@ -1098,15 +1149,18 @@
1098 fill_desktop_file_table (self, directories, *desktop_file_table,1149 fill_desktop_file_table (self, directories, *desktop_file_table,
1099 *desktop_id_table, *desktop_class_table);1150 *desktop_id_table, *desktop_class_table);
1100 1151
1101 g_list_free_full (directories, (GDestroyNotify) g_free);1152 g_list_free_full (directories, g_free);
1102}1153}
11031154
1104static gboolean1155static gboolean
1105is_open_office_window (BamfMatcher * self, BamfLegacyWindow * window)1156is_open_office_window (BamfMatcher * self, BamfLegacyWindow * window)
1106{1157{
1107 return g_str_has_prefix (bamf_legacy_window_get_class_name (window), "OpenOffice") ||1158 const char *class_name = bamf_legacy_window_get_class_name (window);
1108 g_str_has_prefix (bamf_legacy_window_get_class_name (window), "LibreOffice") ||1159
1109 g_str_has_prefix (bamf_legacy_window_get_class_name (window), "libreoffice");1160 return (g_str_has_prefix (class_name, "LibreOffice") ||
1161 g_str_has_prefix (class_name, "libreoffice") ||
1162 g_str_has_prefix (class_name, "OpenOffice") ||
1163 g_str_has_prefix (class_name, "openoffice"));
1110}1164}
11111165
1112static char *1166static char *
@@ -1298,7 +1352,7 @@
1298 1352
1299 if (trimmed)1353 if (trimmed)
1300 {1354 {
1301 if (strlen (trimmed) > 0)1355 if (trimmed[0] != '\0')
1302 {1356 {
1303 table_list = g_hash_table_lookup (priv->desktop_file_table, trimmed);1357 table_list = g_hash_table_lookup (priv->desktop_file_table, trimmed);
1304 1358
@@ -1371,7 +1425,7 @@
1371 hint = get_window_hint (self, window, _NET_WM_DESKTOP_FILE);1425 hint = get_window_hint (self, window, _NET_WM_DESKTOP_FILE);
1372 const char *window_class = bamf_legacy_window_get_class_name (window);1426 const char *window_class = bamf_legacy_window_get_class_name (window);
13731427
1374 if (hint && strlen (hint) > 0 && !is_web_app_window(self, window))1428 if (hint && hint[0] != '\0' && !is_web_app_window(self, window))
1375 {1429 {
1376 desktop_files = g_list_prepend (desktop_files, hint);1430 desktop_files = g_list_prepend (desktop_files, hint);
1377 /* whew, hard work, didn't even have to make a copy! */1431 /* whew, hard work, didn't even have to make a copy! */
@@ -1569,13 +1623,7 @@
1569 g_object_unref (best);1623 g_object_unref (best);
1570 }1624 }
15711625
1572 for (l = possible_apps; l; l = l->next)1626 g_list_free_full (possible_apps, g_free);
1573 {
1574 char *str = l->data;
1575 g_free (str);
1576 }
1577
1578 g_list_free (possible_apps);
15791627
1580 bamf_view_add_child (BAMF_VIEW (best), BAMF_VIEW (bamf_window));1628 bamf_view_add_child (BAMF_VIEW (best), BAMF_VIEW (bamf_window));
1581}1629}
@@ -1590,7 +1638,7 @@
1590 GHashTable *registered_pids;1638 GHashTable *registered_pids;
1591 char *window_hint = NULL;1639 char *window_hint = NULL;
1592 gint i, pid;1640 gint i, pid;
1593 gint *key;1641 gpointer key;
15941642
1595 g_return_if_fail (BAMF_IS_MATCHER (self));1643 g_return_if_fail (BAMF_IS_MATCHER (self));
1596 g_return_if_fail (BAMF_IS_LEGACY_WINDOW (window));1644 g_return_if_fail (BAMF_IS_LEGACY_WINDOW (window));
@@ -1604,9 +1652,7 @@
16041652
1605 if (pid > 0)1653 if (pid > 0)
1606 {1654 {
1607 key = g_new (gint, 1);1655 gpointer key = GINT_TO_POINTER (pid);
1608 *key = pid;
1609
1610 const char* result = g_hash_table_lookup (registered_pids, key);1656 const char* result = g_hash_table_lookup (registered_pids, key);
1611 if (result && g_str_has_prefix (result, "/home/"))1657 if (result && g_str_has_prefix (result, "/home/"))
1612 {1658 {
@@ -1618,48 +1664,45 @@
1618 }1664 }
16191665
1620 window_hint = get_window_hint (self, window, _NET_WM_DESKTOP_FILE);1666 window_hint = get_window_hint (self, window, _NET_WM_DESKTOP_FILE);
1621 if (window_hint && strlen (window_hint) > 0)1667 if (window_hint)
1622 {1668 {
1623 /* already set, make sure we know about this1669 if (window_hint[0] != '\0')
1624 * fact for future windows of this applications */
1625 pid = bamf_legacy_window_get_pid (window);
1626
1627 if (pid > 0)
1628 {1670 {
1629 key = g_new (gint, 1);1671 /* already set, make sure we know about this
1630 *key = pid;1672 * fact for future windows of this applications */
1673 pid = bamf_legacy_window_get_pid (window);
16311674
1632 if (!g_hash_table_lookup (registered_pids, key))1675 if (pid > 0)
1633 {1676 {
1634 g_hash_table_insert (registered_pids, key, g_strdup (window_hint));1677 key = GINT_TO_POINTER (pid);
1678
1679 if (!g_hash_table_lookup (registered_pids, key))
1680 {
1681 g_hash_table_insert (registered_pids, key, g_strdup (window_hint));
1682 }
1635 }1683 }
1684
1685 g_free (window_hint);
1686 return;
1636 }1687 }
16371688
1638 g_free (window_hint);1689 g_free (window_hint);
1639 return;1690 window_hint = NULL;
1640 }1691 }
16411692
1642 if (is_open_office_window (self, window))1693 pids = pid_parent_tree (self, bamf_legacy_window_get_pid (window));
1643 {1694
1644 window_hint = get_open_office_window_hint (self, window);1695 for (i = 0; i < pids->len; i++)
1645 }1696 {
1646 else1697 pid = g_array_index (pids, gint, i);
1647 {1698 key = GINT_TO_POINTER (pid);
1648 pids = pid_parent_tree (self, bamf_legacy_window_get_pid (window));1699
16491700 window_hint = g_hash_table_lookup (registered_pids, key);
1650 for (i = 0; i < pids->len; i++)1701 if (window_hint != NULL && window_hint[0] != '\0')
1651 {1702 break;
1652 pid = g_array_index (pids, gint, i);1703 }
16531704
1654 key = g_new (gint, 1);1705 g_array_free (pids, TRUE);
1655 *key = pid;
1656
1657 window_hint = g_hash_table_lookup (registered_pids, key);
1658 if (window_hint != NULL && strlen (window_hint) > 0)
1659 break;
1660 }
1661 g_array_free (pids, TRUE);
1662 }
16631706
1664 if (window_hint)1707 if (window_hint)
1665 set_window_hint (self, window, _NET_WM_DESKTOP_FILE, window_hint);1708 set_window_hint (self, window, _NET_WM_DESKTOP_FILE, window_hint);
@@ -1690,24 +1733,31 @@
1690 bamf_matcher_setup_window_state (self, bamfwindow);1733 bamf_matcher_setup_window_state (self, bamfwindow);
1691}1734}
16921735
1693static gboolean1736static void
1694open_office_window_setup_timer (OpenOfficeTimeoutArgs *args)1737on_open_office_window_name_changed (BamfLegacyWindow *window, BamfMatcher* self)
1695{1738{
1696 if (bamf_legacy_window_is_closed (args->window))1739 g_return_if_fail (BAMF_IS_MATCHER (self));
1697 {1740 g_return_if_fail (BAMF_IS_LEGACY_WINDOW (window));
1698 g_object_unref (args->window);1741
1699 return FALSE;1742 char *old_hint;
1700 }1743 const char *new_hint;
17011744
1702 args->count++;1745 old_hint = get_window_hint (self, window, _NET_WM_DESKTOP_FILE);
1703 if (args->count > 20 || get_open_office_window_hint (args->matcher, args->window)) 1746 new_hint = get_open_office_window_hint (self, window);
1747
1748 if (new_hint && g_strcmp0 (new_hint, old_hint) != 0)
1704 {1749 {
1705 g_object_unref (args->window);1750 bamf_legacy_window_reopen (window);
1706 handle_raw_window (args->matcher, args->window);
1707 return FALSE;
1708 }1751 }
1709 1752
1710 return TRUE;1753 g_free (old_hint);
1754}
1755
1756static void
1757on_open_office_window_closed (BamfLegacyWindow *window, BamfMatcher* self)
1758{
1759 g_signal_handlers_disconnect_by_func (window, on_open_office_window_name_changed, self);
1760 g_object_unref (window);
1711}1761}
17121762
1713static void1763static void
@@ -1724,24 +1774,35 @@
1724 bamf_matcher_register_view (self, BAMF_VIEW (bamfwindow));1774 bamf_matcher_register_view (self, BAMF_VIEW (bamfwindow));
1725 g_object_unref (bamfwindow);1775 g_object_unref (bamfwindow);
1726 1776
1727 return; 1777 return;
1728 }1778 }
17291779
1730 if (is_open_office_window (self, window) && get_open_office_window_hint (self, window) == NULL)1780 if (is_open_office_window (self, window))
1731 {1781 {
1732 OpenOfficeTimeoutArgs* args = (OpenOfficeTimeoutArgs*) g_malloc0 (sizeof (OpenOfficeTimeoutArgs));1782 BamfWindowType win_type = bamf_legacy_window_get_window_type (window);
1733 args->matcher = self;1783
1734 args->window = window;1784 if (win_type == BAMF_WINDOW_SPLASHSCREEN || win_type == BAMF_WINDOW_TOOLBAR)
1735 1785 {
1786 return;
1787 }
1788
1789 char *old_hint = get_window_hint (self, window, _NET_WM_DESKTOP_FILE);
1790 const char *new_hint = get_open_office_window_hint (self, window);
1791
1792 if (new_hint && g_strcmp0 (old_hint, new_hint) != 0)
1793 {
1794 set_window_hint (self, window, _NET_WM_DESKTOP_FILE, new_hint);
1795 }
1796
1736 g_object_ref (window);1797 g_object_ref (window);
1737 /* we have an open office window who is not ready to match yet */1798 g_signal_connect (window, "name-changed", (GCallback) on_open_office_window_name_changed, self);
1738 g_timeout_add (100, (GSourceFunc) open_office_window_setup_timer, args);1799 g_signal_connect (window, "closed", (GCallback) on_open_office_window_closed, self);
1739 }1800
1740 else1801 g_free (old_hint);
1741 {1802 }
1742 /* we have a window who is ready to be matched */1803
1743 handle_raw_window (self, window); 1804 /* we have a window who is ready to be matched */
1744 }1805 handle_raw_window (self, window);
1745}1806}
17461807
1747static void1808static void
@@ -1806,14 +1867,7 @@
1806 }1867 }
1807 }1868 }
18081869
1809 for (l = possible_apps; l; l = l->next)1870 g_list_free_full (possible_apps, g_free);
1810 {
1811 char *str = l->data;
1812 g_free (str);
1813 }
1814
1815
1816 g_list_free (possible_apps);
18171871
1818 if (best)1872 if (best)
1819 bamf_view_add_child (BAMF_VIEW (best), BAMF_VIEW (indicator));1873 bamf_view_add_child (BAMF_VIEW (best), BAMF_VIEW (indicator));
@@ -1847,20 +1901,16 @@
1847 const char * desktopFile,1901 const char * desktopFile,
1848 gint pid)1902 gint pid)
1849{1903{
1850 gint *key;1904 gpointer key;
1851 BamfLegacyScreen *screen;1905 BamfLegacyScreen *screen;
1852 GList *glist_item;1906 GList *glist_item;
1853 GList *windows;1907 GList *windows;
1854 char *dup;
18551908
1856 g_return_if_fail (BAMF_IS_MATCHER (self));1909 g_return_if_fail (BAMF_IS_MATCHER (self));
1857 g_return_if_fail (desktopFile);1910 g_return_if_fail (desktopFile);
18581911
1859 key = g_new (gint, 1);1912 key = GINT_TO_POINTER (pid);
1860 *key = pid;1913 g_hash_table_insert (self->priv->registered_pids, key, g_strdup (desktopFile));
1861
1862 dup = g_strdup (desktopFile);
1863 g_hash_table_insert (self->priv->registered_pids, key, dup);
18641914
1865 /* fixme, this is a bit heavy */1915 /* fixme, this is a bit heavy */
18661916
@@ -2217,8 +2267,8 @@
22172267
2218 priv->known_pids = g_array_new (FALSE, TRUE, sizeof (gint));2268 priv->known_pids = g_array_new (FALSE, TRUE, sizeof (gint));
2219 priv->bad_prefixes = g_array_new (FALSE, TRUE, sizeof (GRegex *));2269 priv->bad_prefixes = g_array_new (FALSE, TRUE, sizeof (GRegex *));
2220 priv->registered_pids =2270 priv->registered_pids = g_hash_table_new_full (g_direct_hash, g_direct_equal,
2221 g_hash_table_new ((GHashFunc) g_int_hash, (GEqualFunc) g_int_equal);2271 NULL, g_free);
22222272
2223 prefixstrings = prefix_strings (self);2273 prefixstrings = prefix_strings (self);
2224 for (i = 0; i < prefixstrings->len; i++)2274 for (i = 0; i < prefixstrings->len; i++)
@@ -2252,13 +2302,61 @@
2252}2302}
22532303
2254static void2304static void
2305bamf_matcher_finalize (GObject *object)
2306{
2307 BamfMatcher *self = (BamfMatcher *) object;
2308 BamfMatcherPrivate *priv = self->priv;
2309 GList *l;
2310 int i;
2311
2312 for (i = 0; i < priv->bad_prefixes->len; i++)
2313 {
2314 GRegex *regex = g_array_index (priv->bad_prefixes, GRegex *, i);
2315 g_regex_unref (regex);
2316 }
2317
2318 g_array_free (priv->bad_prefixes, TRUE);
2319 g_array_free (priv->known_pids, TRUE);
2320 g_hash_table_destroy (priv->desktop_id_table);
2321 g_hash_table_destroy (priv->desktop_file_table);
2322 g_hash_table_destroy (priv->desktop_class_table);
2323 g_hash_table_destroy (priv->registered_pids);
2324
2325 for (l = priv->views; l; l = l->next)
2326 {
2327 bamf_matcher_unregister_view (self, (BamfView*)l->data, FALSE);
2328 }
2329 g_list_free_full (priv->views, g_object_unref);
2330 priv->views = NULL;
2331
2332 for (l = priv->monitors; l; l = l->next)
2333 {
2334 g_signal_handlers_disconnect_by_func (G_OBJECT (l->data),
2335 (GCallback) on_monitor_changed, self);
2336 }
2337 g_list_free_full (priv->monitors, g_object_unref);
2338 priv->monitors = NULL;
2339
2340 g_list_free_full (priv->favorites, g_free);
2341 priv->favorites = NULL;
2342
2343 priv->active_app = NULL;
2344 priv->active_win = NULL;
2345
2346 G_OBJECT_CLASS (bamf_matcher_parent_class)->finalize (object);
2347}
2348
2349static void
2255bamf_matcher_class_init (BamfMatcherClass * klass)2350bamf_matcher_class_init (BamfMatcherClass * klass)
2256{2351{
2352 GObjectClass *object_class = G_OBJECT_CLASS (klass);
2257 g_type_class_add_private (klass, sizeof (BamfMatcherPrivate));2353 g_type_class_add_private (klass, sizeof (BamfMatcherPrivate));
22582354
2259 dbus_g_object_type_install_info (BAMF_TYPE_MATCHER,2355 dbus_g_object_type_install_info (BAMF_TYPE_MATCHER,
2260 &dbus_glib_bamf_matcher_object_info);2356 &dbus_glib_bamf_matcher_object_info);
22612357
2358 object_class->finalize = bamf_matcher_finalize;
2359
2262 matcher_signals [VIEW_OPENED] =2360 matcher_signals [VIEW_OPENED] =
2263 g_signal_new ("view-opened",2361 g_signal_new ("view-opened",
2264 G_OBJECT_CLASS_TYPE (klass),2362 G_OBJECT_CLASS_TYPE (klass),
@@ -2294,7 +2392,7 @@
2294 bamf_marshal_VOID__STRING_STRING,2392 bamf_marshal_VOID__STRING_STRING,
2295 G_TYPE_NONE, 2,2393 G_TYPE_NONE, 2,
2296 G_TYPE_STRING, G_TYPE_STRING);2394 G_TYPE_STRING, G_TYPE_STRING);
2297 2395
2298 matcher_signals [FAVORITES_CHANGED] =2396 matcher_signals [FAVORITES_CHANGED] =
2299 g_signal_new ("favorites-changed",2397 g_signal_new ("favorites-changed",
2300 G_OBJECT_CLASS_TYPE (klass),2398 G_OBJECT_CLASS_TYPE (klass),
23012399
=== modified file 'src/bamf-view.c'
--- src/bamf-view.c 2011-11-29 08:06:28 +0000
+++ src/bamf-view.c 2011-12-15 11:35:15 +0000
@@ -470,8 +470,14 @@
470470
471 g_return_val_if_fail (bus, NULL);471 g_return_val_if_fail (bus, NULL);
472472
473 GObject *old_object = dbus_g_connection_lookup_g_object (bus, path);
474 if (G_IS_OBJECT (old_object))
475 {
476 g_critical ("BAMF has already registered an object on path \"%s`, this should never happen!", path);
477 dbus_g_connection_unregister_g_object (bus, old_object);
478 }
479
473 dbus_g_connection_register_g_object (bus, path, G_OBJECT (view));480 dbus_g_connection_register_g_object (bus, path, G_OBJECT (view));
474
475 g_signal_emit (view, view_signals[EXPORTED], 0);481 g_signal_emit (view, view_signals[EXPORTED], 0);
476 }482 }
477483

Subscribers

People subscribed via source and target branches