Back to index

bamf  0.2.120
bamf-window.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-view-private.h"
00038 #include "bamf-window.h"
00039 #include "bamf-factory.h"
00040 #include "bamf-marshal.h"
00041 #include <dbus/dbus.h>
00042 #include <dbus/dbus-glib.h>
00043 #include <dbus/dbus-glib-lowlevel.h>
00044 
00045 G_DEFINE_TYPE (BamfWindow, bamf_window, BAMF_TYPE_VIEW);
00046 
00047 #define BAMF_WINDOW_GET_PRIVATE(o) \
00048   (G_TYPE_INSTANCE_GET_PRIVATE ((o), BAMF_TYPE_WINDOW, BamfWindowPrivate))
00049 
00050 struct _BamfWindowPrivate
00051 {
00052   DBusGConnection *connection;
00053   DBusGProxy      *proxy;
00054   guint32          xid;
00055   guint32          pid;
00056   time_t           last_active;
00057   gint             monitor;
00058   BamfWindowMaximizationType maximized;
00059 };
00060 
00061 enum
00062 {
00063   MONITOR_CHANGED,
00064   MAXIMIZED_CHANGED,
00065 
00066   LAST_SIGNAL,
00067 };
00068 
00069 static guint window_signals[LAST_SIGNAL] = { 0 };
00070 
00071 time_t bamf_window_last_active (BamfWindow *self)
00072 {
00073   g_return_val_if_fail (BAMF_IS_WINDOW (self), (time_t) 0);
00074   
00075   return self->priv->last_active;
00076 }
00077 
00078 BamfWindow * bamf_window_get_transient (BamfWindow *self)
00079 {
00080   BamfWindowPrivate *priv;
00081   BamfView *transient;
00082   char *path = NULL;
00083   GError *error = NULL;
00084 
00085   g_return_val_if_fail (BAMF_IS_WINDOW (self), FALSE);
00086   priv = self->priv;
00087 
00088   if (!_bamf_view_remote_ready (BAMF_VIEW (self)))
00089     return NULL;
00090 
00091   if (!dbus_g_proxy_call (priv->proxy,
00092                           "Transient",
00093                           &error,
00094                           G_TYPE_INVALID,
00095                           G_TYPE_STRING, &path,
00096                           G_TYPE_INVALID))
00097     {
00098       g_warning ("Failed to fetch path: %s", error->message);
00099       g_error_free (error);
00100       return 0;
00101     }
00102   
00103   if (!path)
00104     return NULL;
00105 
00106   BamfFactory *factory = _bamf_factory_get_default ();
00107   transient = _bamf_factory_view_for_path_type (factory, path, BAMF_FACTORY_WINDOW);
00108   g_free (path);  
00109 
00110   if (!BAMF_IS_WINDOW (transient))
00111     return NULL;
00112     
00113   return BAMF_WINDOW (transient);
00114 }
00115 
00116 BamfWindowType bamf_window_get_window_type (BamfWindow *self)
00117 {
00118   BamfWindowPrivate *priv;
00119   guint32 type = 0;
00120   GError *error = NULL;
00121 
00122   g_return_val_if_fail (BAMF_IS_WINDOW (self), FALSE);
00123   priv = self->priv;
00124 
00125   if (!_bamf_view_remote_ready (BAMF_VIEW (self)))
00126     return 0;
00127 
00128   if (!dbus_g_proxy_call (priv->proxy,
00129                           "WindowType",
00130                           &error,
00131                           G_TYPE_INVALID,
00132                           G_TYPE_UINT, &type,
00133                           G_TYPE_INVALID))
00134     {
00135       g_warning ("Failed to fetch type: %s", error->message);
00136       g_error_free (error);
00137       return 0;
00138     }
00139 
00140   return (BamfWindowType) type;
00141 }
00142 
00143 guint32 bamf_window_get_pid (BamfWindow *self)
00144 {
00145   BamfWindowPrivate *priv;
00146   guint32 pid = 0;
00147   GError *error = NULL;
00148 
00149   g_return_val_if_fail (BAMF_IS_WINDOW (self), FALSE);
00150   priv = self->priv;
00151 
00152   if (priv->pid != 0)
00153     return priv->pid;
00154 
00155   if (!_bamf_view_remote_ready (BAMF_VIEW (self)))
00156     return 0;
00157 
00158   if (!dbus_g_proxy_call (priv->proxy,
00159                           "GetPid",
00160                           &error,
00161                           G_TYPE_INVALID,
00162                           G_TYPE_UINT, &pid,
00163                           G_TYPE_INVALID))
00164     {
00165       g_warning ("Failed to fetch pid: %s", error->message);
00166       g_error_free (error);
00167       return 0;
00168     }
00169 
00170   return pid;
00171 }
00172 
00173 guint32 bamf_window_get_xid (BamfWindow *self)
00174 {
00175   BamfWindowPrivate *priv;
00176   guint32 xid = 0;
00177   GError *error = NULL;
00178   
00179   g_return_val_if_fail (BAMF_IS_WINDOW (self), FALSE);
00180   priv = self->priv;
00181   
00182   if (priv->xid != 0)
00183     return priv->xid;
00184 
00185   if (!_bamf_view_remote_ready (BAMF_VIEW (self)))
00186     return 0;
00187 
00188   if (!dbus_g_proxy_call (priv->proxy,
00189                           "GetXid",
00190                           &error,
00191                           G_TYPE_INVALID,
00192                           G_TYPE_UINT, &xid,
00193                           G_TYPE_INVALID))
00194     {
00195       g_warning ("Failed to fetch xid: %s", error->message);
00196       g_error_free (error);
00197       return 0;
00198     }
00199 
00200   return xid;
00201 }
00202 
00203 static void
00204 bamf_window_active_changed (BamfView *view, gboolean active)
00205 {
00206   BamfWindow *self;
00207 
00208   g_return_if_fail (BAMF_IS_WINDOW (view));
00209 
00210   self = BAMF_WINDOW (view);
00211   
00212   if (active)
00213     self->priv->last_active = time (NULL);
00214 }
00215 
00216 static void
00217 bamf_window_on_monitor_changed (DBusGProxy *proxy, gint old, gint new, BamfWindow *self)
00218 {
00219   self->priv->monitor = new;
00220   g_signal_emit (G_OBJECT (self), window_signals[MONITOR_CHANGED], 0, old, new);
00221 }
00222 
00223 static void
00224 bamf_window_on_maximized_changed (DBusGProxy *proxy, gint old, gint new, BamfWindow *self)
00225 {
00226   self->priv->maximized = new;
00227   g_signal_emit (G_OBJECT (self), window_signals[MAXIMIZED_CHANGED], 0, old, new);
00228 }
00229 
00230 static void
00231 bamf_window_unset_proxy (BamfWindow *self)
00232 {
00233   BamfWindowPrivate *priv;
00234 
00235   g_return_if_fail (BAMF_IS_WINDOW (self));
00236   priv = self->priv;
00237 
00238   if (!priv->proxy)
00239     return;
00240 
00241   dbus_g_proxy_disconnect_signal (self->priv->proxy,
00242                                   "MaximizedChanged",
00243                                   (GCallback) bamf_window_on_maximized_changed,
00244                                   self);
00245 
00246   dbus_g_proxy_disconnect_signal (self->priv->proxy,
00247                                   "MonitorChanged",
00248                                   (GCallback) bamf_window_on_monitor_changed,
00249                                   self);
00250 
00251   g_object_unref (priv->proxy);
00252   priv->proxy = NULL;
00253 }
00254 
00255 static void
00256 bamf_window_set_path (BamfView *view, const char *path)
00257 {
00258   BamfWindow *self;
00259   BamfWindowPrivate *priv;
00260   
00261   self = BAMF_WINDOW (view);
00262   priv = self->priv;
00263 
00264   bamf_window_unset_proxy (self);
00265   priv->proxy = dbus_g_proxy_new_for_name (priv->connection,
00266                                            "org.ayatana.bamf",
00267                                            path,
00268                                            "org.ayatana.bamf.window");
00269   if (priv->proxy == NULL)
00270     {
00271       g_error ("Unable to get org.ayatana.bamf.window window");
00272       return;
00273     }
00274 
00275   priv->xid = bamf_window_get_xid (self);
00276   priv->monitor = bamf_window_get_monitor (self);
00277   priv->maximized = bamf_window_maximized (self);
00278 
00279   dbus_g_object_register_marshaller ((GClosureMarshal) _bamf_marshal_VOID__INT_INT,
00280                                      G_TYPE_NONE, 
00281                                      G_TYPE_INT, G_TYPE_INT,
00282                                      G_TYPE_INVALID);
00283 
00284   dbus_g_proxy_add_signal (priv->proxy,
00285                            "MonitorChanged",
00286                            G_TYPE_INT,
00287                            G_TYPE_INT,
00288                            G_TYPE_INVALID);
00289 
00290   dbus_g_proxy_connect_signal (priv->proxy,
00291                                "MonitorChanged",
00292                                (GCallback) bamf_window_on_monitor_changed,
00293                                self, NULL);
00294 
00295   dbus_g_proxy_add_signal (priv->proxy,
00296                            "MaximizedChanged",
00297                            G_TYPE_INT,
00298                            G_TYPE_INT,
00299                            G_TYPE_INVALID);
00300 
00301   dbus_g_proxy_connect_signal (priv->proxy,
00302                                "MaximizedChanged",
00303                                (GCallback) bamf_window_on_maximized_changed,
00304                                self, NULL);
00305 }
00306 
00307 gchar *
00308 bamf_window_get_utf8_prop (BamfWindow *self, const char* xprop)
00309 {
00310   BamfWindowPrivate *priv;
00311   char *result = NULL;
00312   GError *error = NULL;
00313 
00314   g_return_val_if_fail (BAMF_IS_WINDOW (self), NULL);
00315   priv = self->priv;
00316 
00317   if (!_bamf_view_remote_ready (BAMF_VIEW (self)))
00318     return NULL;
00319 
00320   if (!dbus_g_proxy_call (priv->proxy,
00321                           "Xprop",
00322                           &error,
00323                           G_TYPE_STRING, xprop,
00324                           G_TYPE_INVALID,
00325                           G_TYPE_STRING, &result,
00326                           G_TYPE_INVALID))
00327     {
00328       g_warning ("Failed to fetch property: %s", error->message);
00329       g_error_free (error);
00330 
00331       return NULL;
00332     }
00333 
00334   if (result && result[0] == '\0')
00335     {
00336       g_free (result);
00337       result = NULL;
00338     }
00339 
00340   return result;
00341 }
00342 
00343 gint
00344 bamf_window_get_monitor (BamfWindow *self)
00345 {
00346   BamfWindowPrivate *priv;
00347   gint monitor = -2;
00348   GError *error = NULL;
00349 
00350   g_return_val_if_fail (BAMF_IS_WINDOW (self), -1);
00351   priv = self->priv;
00352 
00353   if (priv->monitor != -2 || !_bamf_view_remote_ready (BAMF_VIEW (self)))
00354     {
00355       return priv->monitor;
00356     }
00357 
00358   if (!dbus_g_proxy_call (priv->proxy,
00359                           "Monitor",
00360                           &error,
00361                           G_TYPE_INVALID,
00362                           G_TYPE_INT, &monitor,
00363                           G_TYPE_INVALID))
00364     {
00365       g_warning ("Failed to fetch monitor: %s", error->message);
00366       g_error_free (error);
00367 
00368       return -1;
00369     }
00370 
00371   return monitor;
00372 }
00373 
00374 BamfWindowMaximizationType
00375 bamf_window_maximized (BamfWindow *self)
00376 {
00377   BamfWindowPrivate *priv;
00378   BamfWindowMaximizationType maximized = -1;
00379   GError *error = NULL;
00380 
00381   g_return_val_if_fail (BAMF_IS_WINDOW (self), -1);
00382   priv = self->priv;
00383 
00384   if (priv->maximized != -1 || !_bamf_view_remote_ready (BAMF_VIEW (self)))
00385     {
00386       return priv->maximized;
00387     }
00388 
00389   if (!dbus_g_proxy_call (priv->proxy,
00390                           "Maximized",
00391                           &error,
00392                           G_TYPE_INVALID,
00393                           G_TYPE_INT, &maximized,
00394                           G_TYPE_INVALID))
00395     {
00396       g_warning ("Failed to fetch maximized state: %s", error->message);
00397       g_error_free (error);
00398 
00399       return -1;
00400     }
00401 
00402   return maximized;
00403 }
00404 
00405 static void
00406 bamf_window_dispose (GObject *object)
00407 {
00408   BamfWindow *self;
00409   
00410   self = BAMF_WINDOW (object);
00411   bamf_window_unset_proxy (self);
00412 
00413   if (G_OBJECT_CLASS (bamf_window_parent_class)->dispose)
00414     G_OBJECT_CLASS (bamf_window_parent_class)->dispose (object);
00415 }
00416 
00417 static void
00418 bamf_window_class_init (BamfWindowClass *klass)
00419 {
00420   GObjectClass  *obj_class  = G_OBJECT_CLASS (klass);
00421   BamfViewClass *view_class = BAMF_VIEW_CLASS (klass);
00422 
00423   g_type_class_add_private (obj_class, sizeof (BamfWindowPrivate));
00424   
00425   obj_class->dispose     = bamf_window_dispose;
00426   view_class->active_changed = bamf_window_active_changed;
00427   view_class->set_path   = bamf_window_set_path;
00428   
00429   window_signals[MONITOR_CHANGED] = 
00430     g_signal_new ("monitor-changed",
00431                   G_OBJECT_CLASS_TYPE (klass),
00432                   G_SIGNAL_RUN_FIRST,
00433                   G_STRUCT_OFFSET (BamfWindowClass, monitor_changed),
00434                   NULL, NULL,
00435                   _bamf_marshal_VOID__INT_INT,
00436                   G_TYPE_NONE, 2,
00437                   G_TYPE_INT, G_TYPE_INT);
00438 
00439   window_signals[MAXIMIZED_CHANGED] = 
00440     g_signal_new ("maximized-changed",
00441                   G_OBJECT_CLASS_TYPE (klass),
00442                   G_SIGNAL_RUN_FIRST,
00443                   G_STRUCT_OFFSET (BamfWindowClass, maximized_changed),
00444                   NULL, NULL,
00445                   _bamf_marshal_VOID__INT_INT,
00446                   G_TYPE_NONE, 2,
00447                   G_TYPE_INT, G_TYPE_INT);
00448 }
00449 
00450 static void
00451 bamf_window_init (BamfWindow *self)
00452 {
00453   BamfWindowPrivate *priv;
00454   GError           *error = NULL;
00455 
00456   priv = self->priv = BAMF_WINDOW_GET_PRIVATE (self);
00457 
00458   priv->xid = 0;
00459   priv->pid = 0;
00460   priv->monitor = -2;
00461   priv->maximized = -1;
00462 
00463   priv->connection = dbus_g_bus_get (DBUS_BUS_SESSION, &error);
00464   if (priv->connection == NULL)
00465     {
00466       g_critical ("Failed to open connection to bus: %s",
00467                error != NULL ? error->message : "Unknown");
00468       if (error)
00469         g_error_free (error);
00470       return;
00471     }
00472 }
00473 
00474 BamfWindow *
00475 bamf_window_new (const char * path)
00476 {
00477   BamfWindow *self;
00478   self = g_object_new (BAMF_TYPE_WINDOW, NULL);
00479 
00480   _bamf_view_set_path (BAMF_VIEW (self), path);
00481 
00482   return self;
00483 }