Back to index

bamf  0.2.120
bamf-matcher.c
Go to the documentation of this file.
00001 /*
00002  * Copyright 2010 Canonical Ltd.
00003  *
00004  * This program is free software: you can redistribute it and/or modify it
00005  * under the terms of either or both of the following licenses:
00006  *
00007  * 1) the GNU Lesser General Public License version 3, as published by the
00008  * Free Software Foundation; and/or
00009  * 2) the GNU Lesser General Public License version 2.1, as published by
00010  * the Free Software Foundation.
00011  *
00012  * This program is distributed in the hope that it will be useful, but
00013  * WITHOUT ANY WARRANTY; without even the implied warranties of
00014  * MERCHANTABILITY, SATISFACTORY QUALITY or FITNESS FOR A PARTICULAR
00015  * PURPOSE.  See the applicable version of the GNU Lesser General Public
00016  * License for more details.
00017  *
00018  * You should have received a copy of both the GNU Lesser General Public
00019  * License version 3 and version 2.1 along with this program.  If not, see
00020  * <http://www.gnu.org/licenses/>
00021  *
00022  * Authored by: Jason Smith <jason.smith@canonical.com>
00023  *              Neil Jagdish Patel <neil.patel@canonical.com>
00024  *
00025  */
00033 #if HAVE_CONFIG_H
00034 #include <config.h>
00035 #endif
00036 
00037 #include "bamf-matcher.h"
00038 #include "bamf-view.h"
00039 #include "bamf-view-private.h"
00040 #include "bamf-factory.h"
00041 #include "bamf-marshal.h"
00042 
00043 #include <string.h>
00044 #include <dbus/dbus.h>
00045 #include <dbus/dbus-glib.h>
00046 #include <dbus/dbus-glib-lowlevel.h>
00047 
00048 G_DEFINE_TYPE (BamfMatcher, bamf_matcher, G_TYPE_OBJECT);
00049 
00050 #define BAMF_MATCHER_GET_PRIVATE(o) \
00051   (G_TYPE_INSTANCE_GET_PRIVATE ((o), BAMF_TYPE_MATCHER, BamfMatcherPrivate))
00052 
00053 enum
00054 {
00055   VIEW_OPENED,
00056   VIEW_CLOSED,
00057   ACTIVE_APPLICATION_CHANGED,
00058   ACTIVE_WINDOW_CHANGED,
00059   STACKING_ORDER_CHANGED,
00060   
00061   LAST_SIGNAL,
00062 };
00063 
00064 static guint matcher_signals[LAST_SIGNAL] = { 0 };
00065 
00066 struct _BamfMatcherPrivate
00067 {
00068   DBusGConnection *connection;
00069   DBusGProxy      *proxy;
00070 };
00071 
00072 static BamfMatcher * default_matcher = NULL;
00073 
00074 static void bamf_matcher_dispose (GObject *object);
00075 
00076 static void
00077 bamf_matcher_finalize (GObject *object)
00078 {
00079   default_matcher = NULL;
00080 
00081   G_OBJECT_CLASS (bamf_matcher_parent_class)->finalize (object);
00082 }
00083 
00084 static void
00085 bamf_matcher_class_init (BamfMatcherClass *klass)
00086 {
00087   GObjectClass *obj_class = G_OBJECT_CLASS (klass);
00088 
00089   g_type_class_add_private (obj_class, sizeof (BamfMatcherPrivate));
00090   obj_class->dispose = bamf_matcher_dispose;
00091   obj_class->finalize = bamf_matcher_finalize;
00092 
00093   matcher_signals [VIEW_OPENED] = 
00094     g_signal_new ("view-opened",
00095                   G_OBJECT_CLASS_TYPE (klass),
00096                   0,
00097                   0, NULL, NULL,
00098                   g_cclosure_marshal_VOID__OBJECT,
00099                   G_TYPE_NONE, 1, 
00100                   G_TYPE_OBJECT);
00101 
00102   matcher_signals [VIEW_CLOSED] = 
00103     g_signal_new ("view-closed",
00104                   G_OBJECT_CLASS_TYPE (klass),
00105                   0,
00106                   0, NULL, NULL,
00107                   g_cclosure_marshal_VOID__OBJECT,
00108                   G_TYPE_NONE, 1, 
00109                   G_TYPE_OBJECT);
00110 
00111 
00112   matcher_signals [ACTIVE_APPLICATION_CHANGED] = 
00113     g_signal_new ("active-application-changed",
00114                   G_OBJECT_CLASS_TYPE (klass),
00115                   0,
00116                   0, NULL, NULL,
00117                   _bamf_marshal_VOID__OBJECT_OBJECT,
00118                   G_TYPE_NONE, 2, 
00119                   G_TYPE_OBJECT, G_TYPE_OBJECT);
00120 
00121   matcher_signals [ACTIVE_WINDOW_CHANGED] = 
00122     g_signal_new ("active-window-changed",
00123                   G_OBJECT_CLASS_TYPE (klass),
00124                   0,
00125                   0, NULL, NULL,
00126                   _bamf_marshal_VOID__OBJECT_OBJECT,
00127                   G_TYPE_NONE, 2, 
00128                   G_TYPE_OBJECT, G_TYPE_OBJECT);
00129 
00130   matcher_signals [STACKING_ORDER_CHANGED] = 
00131     g_signal_new ("stacking-order-changed",
00132                   G_OBJECT_CLASS_TYPE (klass),
00133                   0,
00134                   0, NULL, NULL,
00135                   g_cclosure_marshal_VOID__VOID,
00136                   G_TYPE_NONE, 0);
00137 }
00138 
00139 
00140 static void
00141 bamf_matcher_on_view_opened (DBusGProxy *proxy, 
00142                              char *path, 
00143                              char *type, 
00144                              BamfMatcher *matcher)
00145 {
00146   BamfView *view;
00147   BamfFactory *factory = _bamf_factory_get_default ();
00148 
00149   view = _bamf_factory_view_for_path_type_str (factory, path, type);
00150 
00151   if (!BAMF_IS_VIEW (view))
00152     return;
00153 
00154   /* We manually set the view as not closed, to avoid issues like bug #925421 */
00155   _bamf_view_set_closed (view, FALSE);
00156   g_signal_emit (matcher, matcher_signals[VIEW_OPENED], 0, view);
00157 }
00158 
00159 static void
00160 bamf_matcher_on_view_closed (DBusGProxy *proxy, 
00161                              char *path, 
00162                              char *type, 
00163                              BamfMatcher *matcher)
00164 {
00165   BamfView *view;
00166   BamfFactory *factory = _bamf_factory_get_default ();
00167 
00168   view = _bamf_factory_view_for_path_type_str (factory, path, type);
00169 
00170   if (!BAMF_IS_VIEW (view))
00171     return;
00172 
00173   /* We manually set the view as closed, to avoid issues like bug #925421 */
00174   _bamf_view_set_closed (view, TRUE);
00175   g_signal_emit (matcher, matcher_signals[VIEW_CLOSED], 0, view);
00176 }
00177 
00178 static void
00179 bamf_matcher_on_active_application_changed (DBusGProxy *proxy,
00180                                             char *old_path,
00181                                             char *new_path,
00182                                             BamfMatcher *matcher)
00183 {
00184   BamfView *old_view;
00185   BamfView *new_view;
00186 
00187   BamfFactory *factory = _bamf_factory_get_default ();
00188   old_view = _bamf_factory_view_for_path_type (factory, old_path, BAMF_FACTORY_APPLICATION);
00189   new_view = _bamf_factory_view_for_path_type (factory, new_path, BAMF_FACTORY_APPLICATION);
00190 
00191   g_signal_emit (matcher, matcher_signals[ACTIVE_APPLICATION_CHANGED], 0, old_view, new_view);
00192 }
00193 
00194 static void
00195 bamf_matcher_on_active_window_changed (DBusGProxy *proxy,
00196                                        char *old_path,
00197                                        char *new_path,
00198                                        BamfMatcher *matcher)
00199 {
00200   BamfView *old_view;
00201   BamfView *new_view;
00202 
00203   BamfFactory *factory = _bamf_factory_get_default ();
00204   old_view = _bamf_factory_view_for_path_type (factory, old_path, BAMF_FACTORY_WINDOW);
00205   new_view = _bamf_factory_view_for_path_type (factory, new_path, BAMF_FACTORY_WINDOW);
00206 
00207   g_signal_emit (matcher, matcher_signals[ACTIVE_WINDOW_CHANGED], 0, old_view, new_view);
00208 }
00209 
00210 static void
00211 bamf_matcher_on_stacking_order_changed (DBusGProxy *proxy, BamfMatcher *matcher)
00212 {
00213   g_signal_emit (matcher, matcher_signals[STACKING_ORDER_CHANGED], 0);
00214 }
00215 
00216 static void
00217 bamf_matcher_init (BamfMatcher *self)
00218 {
00219   BamfMatcherPrivate *priv;
00220   GError           *error = NULL;
00221 
00222   priv = self->priv = BAMF_MATCHER_GET_PRIVATE (self);
00223 
00224   priv->connection = dbus_g_bus_get (DBUS_BUS_SESSION, &error);
00225   if (priv->connection == NULL || error != NULL)
00226     {
00227       g_error ("Failed to open connection to bus: %s",
00228                error != NULL ? error->message : "Unknown");
00229       if (error)
00230         g_error_free (error);
00231       return;
00232     }
00233 
00234   priv->proxy = dbus_g_proxy_new_for_name (priv->connection,
00235                                            "org.ayatana.bamf",
00236                                            "/org/ayatana/bamf/matcher",
00237                                            "org.ayatana.bamf.matcher");
00238   if (priv->proxy == NULL)
00239     {
00240       g_error ("Unable to get org.ayatana.bamf.matcher matcher");
00241     }
00242 
00243   dbus_g_object_register_marshaller ((GClosureMarshal) _bamf_marshal_VOID__STRING_STRING,
00244                                      G_TYPE_NONE, 
00245                                      G_TYPE_STRING, G_TYPE_STRING,
00246                                      G_TYPE_INVALID);
00247 
00248   dbus_g_proxy_add_signal (priv->proxy,
00249                            "ViewOpened",
00250                            G_TYPE_STRING, 
00251                            G_TYPE_STRING,
00252                            G_TYPE_INVALID);
00253 
00254   dbus_g_proxy_connect_signal (priv->proxy,
00255                                "ViewOpened",
00256                                (GCallback) bamf_matcher_on_view_opened,
00257                                self, NULL);
00258 
00259   dbus_g_proxy_add_signal (priv->proxy,
00260                            "ViewClosed",
00261                            G_TYPE_STRING, 
00262                            G_TYPE_STRING,
00263                            G_TYPE_INVALID);
00264 
00265   dbus_g_proxy_connect_signal (priv->proxy,
00266                                "ViewClosed",
00267                                (GCallback) bamf_matcher_on_view_closed,
00268                                self, NULL);
00269 
00270   dbus_g_proxy_add_signal (priv->proxy,
00271                            "ActiveApplicationChanged",
00272                            G_TYPE_STRING, 
00273                            G_TYPE_STRING,
00274                            G_TYPE_INVALID);
00275 
00276   dbus_g_proxy_connect_signal (priv->proxy,
00277                                "ActiveApplicationChanged",
00278                                (GCallback) bamf_matcher_on_active_application_changed,
00279                                self, NULL);
00280 
00281   dbus_g_proxy_add_signal (priv->proxy,
00282                            "ActiveWindowChanged",
00283                            G_TYPE_STRING, 
00284                            G_TYPE_STRING,
00285                            G_TYPE_INVALID);
00286 
00287   dbus_g_proxy_connect_signal (priv->proxy,
00288                                "ActiveWindowChanged",
00289                                (GCallback) bamf_matcher_on_active_window_changed,
00290                                self, NULL);
00291 
00292   dbus_g_proxy_add_signal (priv->proxy,
00293                            "StackingOrderChanged",
00294                            G_TYPE_INVALID);
00295 
00296   dbus_g_proxy_connect_signal (priv->proxy,
00297                                "StackingOrderChanged",
00298                                (GCallback) bamf_matcher_on_stacking_order_changed,
00299                                self, NULL);
00300 }
00301 
00302 static void
00303 bamf_matcher_dispose (GObject *object)
00304 {
00305   BamfMatcher *self = BAMF_MATCHER (object);
00306   BamfMatcherPrivate *priv = self->priv;
00307 
00308   if (priv->proxy)
00309     {
00310       dbus_g_proxy_disconnect_signal (priv->proxy,
00311                                       "ViewOpened",
00312                                       (GCallback) bamf_matcher_on_view_opened,
00313                                       self);
00314 
00315       dbus_g_proxy_disconnect_signal (priv->proxy,
00316                                       "ViewClosed",
00317                                       (GCallback) bamf_matcher_on_view_closed,
00318                                       self);
00319 
00320       dbus_g_proxy_disconnect_signal (priv->proxy,
00321                                       "ActiveApplicationChanged",
00322                                       (GCallback) bamf_matcher_on_active_application_changed,
00323                                       self);
00324 
00325       dbus_g_proxy_disconnect_signal (priv->proxy,
00326                                       "ActiveWindowChanged",
00327                                       (GCallback) bamf_matcher_on_active_window_changed,
00328                                       self);
00329 
00330       dbus_g_proxy_disconnect_signal (priv->proxy,
00331                                       "StackingOrderChanged",
00332                                       (GCallback) bamf_matcher_on_stacking_order_changed,
00333                                       self);
00334 
00335       g_object_unref (priv->proxy);
00336       priv->proxy = NULL;
00337     }
00338 
00339   G_OBJECT_CLASS (bamf_matcher_parent_class)->dispose (object);
00340 }
00341 
00342 /*
00343  * Private Methods
00344  */
00345 
00346 /*
00347  * Public Methods
00348  */
00349 BamfMatcher *
00350 bamf_matcher_get_default (void)
00351 {
00352   if (BAMF_IS_MATCHER (default_matcher))
00353     return g_object_ref (default_matcher);
00354 
00355   return (default_matcher = g_object_new (BAMF_TYPE_MATCHER, NULL));
00356 }
00357 
00358 BamfApplication *
00359 bamf_matcher_get_active_application (BamfMatcher *matcher)
00360 {
00361   BamfMatcherPrivate *priv;
00362   BamfView *view;
00363   char *app = NULL;
00364   GError *error = NULL;
00365 
00366   g_return_val_if_fail (BAMF_IS_MATCHER (matcher), NULL);
00367   priv = matcher->priv;
00368 
00369   if (!dbus_g_proxy_call (priv->proxy,
00370                           "ActiveApplication",
00371                           &error,
00372                           G_TYPE_INVALID,
00373                           G_TYPE_STRING, &app,
00374                           G_TYPE_INVALID))
00375     {
00376       g_warning ("Failed to fetch path: %s", error->message);
00377       g_error_free (error);
00378       return NULL;
00379     }
00380 
00381   if (app && app[0] == '\0')
00382     {
00383       g_free (app);
00384       return NULL;
00385     }
00386 
00387   if (!app)
00388     return NULL;
00389 
00390   BamfFactory *factory = _bamf_factory_get_default ();
00391   view = _bamf_factory_view_for_path_type (factory, app, BAMF_FACTORY_APPLICATION);
00392   g_free (app);
00393 
00394   if (!BAMF_IS_APPLICATION (view))
00395     return NULL;
00396 
00397   return BAMF_APPLICATION (view);
00398 }
00399 
00400 BamfWindow *
00401 bamf_matcher_get_active_window (BamfMatcher *matcher)
00402 {
00403   BamfMatcherPrivate *priv;
00404   BamfView *view;
00405   char *win = NULL;
00406   GError *error = NULL;
00407 
00408   g_return_val_if_fail (BAMF_IS_MATCHER (matcher), NULL);
00409   priv = matcher->priv;
00410 
00411   if (!dbus_g_proxy_call (priv->proxy,
00412                           "ActiveWindow",
00413                           &error,
00414                           G_TYPE_INVALID,
00415                           G_TYPE_STRING, &win,
00416                           G_TYPE_INVALID))
00417     {
00418       g_warning ("Failed to fetch path: %s", error->message);
00419       g_error_free (error);
00420       return NULL;
00421     }
00422 
00423   if (win && win[0] == '\0')
00424     {
00425       g_free (win);
00426       return NULL;
00427     }
00428 
00429   if (!win)
00430     return NULL;
00431 
00432   BamfFactory *factory = _bamf_factory_get_default ();
00433   view = _bamf_factory_view_for_path_type (factory, win, BAMF_FACTORY_WINDOW);
00434   g_free (win);
00435 
00436   if (!BAMF_IS_WINDOW (view))
00437     return NULL;
00438 
00439   return BAMF_WINDOW (view);
00440 }
00441 
00442 /* Looks up the window's XID and calls the application_for_xid
00443    function just below here. */
00444 BamfApplication * 
00445 bamf_matcher_get_application_for_window  (BamfMatcher *matcher,
00446                                           BamfWindow *window)
00447 {
00448        g_return_val_if_fail(BAMF_IS_WINDOW(window), NULL);
00449        return bamf_matcher_get_application_for_xid (matcher, bamf_window_get_xid(window));
00450 }
00451 
00452 BamfApplication *
00453 bamf_matcher_get_application_for_xid (BamfMatcher  *matcher,
00454                                       guint32       xid)
00455 {
00456   BamfMatcherPrivate *priv;
00457   BamfView *view;
00458   char *app = NULL;
00459   GError *error = NULL;
00460 
00461   g_return_val_if_fail (BAMF_IS_MATCHER (matcher), NULL);
00462   priv = matcher->priv;
00463 
00464   if (!dbus_g_proxy_call (priv->proxy,
00465                           "ApplicationForXid",
00466                           &error,
00467                           G_TYPE_UINT, xid,
00468                           G_TYPE_INVALID,
00469                           G_TYPE_STRING, &app,
00470                           G_TYPE_INVALID))
00471     {
00472       g_warning ("Failed to fetch path: %s", error->message);
00473       g_error_free (error);
00474       return NULL;
00475     }
00476 
00477   if (app && app[0] == '\0')
00478     {
00479       g_free (app);
00480       return NULL;
00481     }
00482 
00483   if (!app)
00484     return NULL;
00485 
00486   BamfFactory *factory = _bamf_factory_get_default ();
00487   view = _bamf_factory_view_for_path_type (factory, app, BAMF_FACTORY_APPLICATION);
00488   
00489   g_free (app);
00490 
00491   if (!BAMF_IS_APPLICATION (view))
00492     return NULL;
00493 
00494   return BAMF_APPLICATION (view);
00495 }
00496 
00497 gboolean
00498 bamf_matcher_application_is_running (BamfMatcher *matcher,
00499                                      const gchar *application)
00500 {
00501   BamfMatcherPrivate *priv;
00502   gboolean running = FALSE;
00503   GError *error = NULL;
00504 
00505   g_return_val_if_fail (BAMF_IS_MATCHER (matcher), FALSE);
00506   priv = matcher->priv;
00507 
00508   if (!dbus_g_proxy_call (priv->proxy,
00509                           "ApplicationIsRunning",
00510                           &error,
00511                           G_TYPE_STRING, application,
00512                           G_TYPE_INVALID,
00513                           G_TYPE_BOOLEAN, &running,
00514                           G_TYPE_INVALID))
00515     {
00516       g_warning ("Failed to fetch path: %s", error->message);
00517       g_error_free (error);
00518       
00519       return FALSE;
00520     }
00521 
00522   return running;
00523 }
00524 
00525 GList *
00526 bamf_matcher_get_applications (BamfMatcher *matcher)
00527 {
00528   BamfMatcherPrivate *priv;
00529   BamfView *view;
00530   char **array = NULL;
00531   int i, len;
00532   GList *result = NULL;
00533   GError *error = NULL;
00534 
00535   g_return_val_if_fail (BAMF_IS_MATCHER (matcher), NULL);
00536   priv = matcher->priv;
00537 
00538   if (!dbus_g_proxy_call (priv->proxy,
00539                           "ApplicationPaths",
00540                           &error,
00541                           G_TYPE_INVALID,
00542                           G_TYPE_STRV, &array,
00543                           G_TYPE_INVALID))
00544     {
00545       g_warning ("Failed to fetch paths: %s", error->message);
00546       g_error_free (error);
00547       
00548       return NULL;
00549     }
00550 
00551   if (!array)
00552     return NULL;
00553 
00554   BamfFactory *factory = _bamf_factory_get_default ();
00555   len = g_strv_length (array);
00556   for (i = len-1; i >= 0; i--)
00557     {
00558       view = _bamf_factory_view_for_path_type (factory, array[i], BAMF_FACTORY_APPLICATION);
00559 
00560       if (BAMF_IS_APPLICATION (view))
00561         result = g_list_prepend (result, view);
00562     }
00563   
00564   g_strfreev (array);
00565   return result;
00566 }
00567 
00568 GList *
00569 bamf_matcher_get_windows (BamfMatcher *matcher)
00570 {
00571   BamfMatcherPrivate *priv;
00572   BamfView *view;
00573   char **array = NULL;
00574   int i, len;
00575   GList *result = NULL;
00576   GError *error = NULL;
00577 
00578   g_return_val_if_fail (BAMF_IS_MATCHER (matcher), NULL);
00579   priv = matcher->priv;
00580 
00581   if (!dbus_g_proxy_call (priv->proxy,
00582                           "WindowPaths",
00583                           &error,
00584                           G_TYPE_INVALID,
00585                           G_TYPE_STRV, &array,
00586                           G_TYPE_INVALID))
00587     {
00588       g_warning ("Failed to fetch paths: %s", error->message);
00589       g_error_free (error);
00590       
00591       return NULL;
00592     }
00593 
00594   if (!array)
00595     return NULL;
00596 
00597   BamfFactory *factory = _bamf_factory_get_default ();
00598   len = g_strv_length (array);
00599   for (i = len-1; i >= 0; i--)
00600     {
00601       view = _bamf_factory_view_for_path_type (factory, array[i], BAMF_FACTORY_WINDOW);
00602 
00603       if (BAMF_IS_WINDOW (view))
00604         result = g_list_prepend (result, view);
00605     }
00606   
00607   g_strfreev (array);
00608   return result;
00609 }
00610 
00611 GList *
00612 bamf_matcher_get_window_stack_for_monitor (BamfMatcher *matcher, gint monitor)
00613 {
00614   BamfMatcherPrivate *priv;
00615   BamfView *view;
00616   char **array = NULL;
00617   int i, len;
00618   GList *result = NULL;
00619   GError *error = NULL;
00620 
00621   g_return_val_if_fail (BAMF_IS_MATCHER (matcher), NULL);
00622   priv = matcher->priv;
00623 
00624   if (!dbus_g_proxy_call (priv->proxy,
00625                           "WindowStackForMonitor",
00626                           &error,
00627                           G_TYPE_INT,
00628                           monitor,
00629                           G_TYPE_INVALID,
00630                           G_TYPE_STRV, &array,
00631                           G_TYPE_INVALID))
00632     {
00633       g_warning ("Failed to fetch paths: %s", error->message);
00634       g_error_free (error);
00635       
00636       return NULL;
00637     }
00638 
00639   if (!array)
00640     return NULL;
00641 
00642   BamfFactory *factory = _bamf_factory_get_default ();
00643   len = g_strv_length (array);
00644   for (i = len-1; i >= 0; i--)
00645     {
00646       view = _bamf_factory_view_for_path_type (factory, array[i], BAMF_FACTORY_WINDOW);
00647 
00648       if (BAMF_IS_WINDOW (view))
00649         result = g_list_prepend (result, view);
00650     }
00651   
00652   g_strfreev (array);
00653   return result;
00654 }
00655 
00656 void
00657 bamf_matcher_register_favorites (BamfMatcher *matcher,
00658                                  const gchar **favorites)
00659 {
00660   BamfMatcherPrivate *priv;
00661 
00662   g_return_if_fail (BAMF_IS_MATCHER (matcher));
00663   g_return_if_fail (favorites);
00664   
00665   priv = matcher->priv;
00666 
00667   dbus_g_proxy_call_no_reply (priv->proxy,
00668                               "RegisterFavorites",
00669                               G_TYPE_STRV, favorites,
00670                               G_TYPE_INVALID);
00671 }
00672 
00673 GList *
00674 bamf_matcher_get_running_applications (BamfMatcher *matcher)
00675 {
00676   BamfMatcherPrivate *priv;
00677   BamfView *view;
00678   char **array = NULL;
00679   int i, len;
00680   GList *result = NULL;
00681   GError *error = NULL;
00682 
00683   g_return_val_if_fail (BAMF_IS_MATCHER (matcher), NULL);
00684   priv = matcher->priv;
00685 
00686   if (!dbus_g_proxy_call (priv->proxy,
00687                           "RunningApplications",
00688                           &error,
00689                           G_TYPE_INVALID,
00690                           G_TYPE_STRV, &array,
00691                           G_TYPE_INVALID))
00692     {
00693       g_warning ("Failed to fetch paths: %s", error->message);
00694       g_error_free (error);
00695       
00696       return NULL;
00697     }
00698 
00699   if (!array)
00700     return NULL;
00701 
00702   BamfFactory *factory = _bamf_factory_get_default ();
00703   len = g_strv_length (array);
00704   for (i = len-1; i >= 0; i--)
00705     {
00706       view = _bamf_factory_view_for_path_type (factory, array[i], BAMF_FACTORY_APPLICATION);
00707 
00708       if (BAMF_IS_APPLICATION (view))
00709         result = g_list_prepend (result, view);
00710     }
00711 
00712   g_strfreev (array);
00713   return result;
00714 }
00715 
00716 GList *
00717 bamf_matcher_get_tabs (BamfMatcher *matcher)
00718 {
00719   /* FIXME */
00720   return NULL;
00721 }
00722 
00723 GArray *
00724 bamf_matcher_get_xids_for_application (BamfMatcher *matcher,
00725                                        const gchar *application)
00726 {
00727   /* FIXME */
00728   return NULL;
00729 }
00730 
00731 BamfApplication * 
00732 bamf_matcher_get_application_for_desktop_file (BamfMatcher *matcher,
00733                                                const gchar *desktop_file_path,
00734                                                gboolean create_if_not_found)
00735 {
00736   BamfApplication *app;
00737   const gchar ** favs;
00738   
00739   app = _bamf_factory_app_for_file (_bamf_factory_get_default (), desktop_file_path, create_if_not_found);
00740   if (app)
00741     {
00742       favs = g_malloc0 (sizeof (gchar *) * 2),
00743       favs[0] = desktop_file_path;      
00744       bamf_matcher_register_favorites (matcher, favs);
00745       g_free (favs);
00746     }
00747   return app;
00748 }