Back to index

bamf  0.2.120
bamf-window.c
Go to the documentation of this file.
00001 /*
00002  * Copyright (C) 2010 Canonical Ltd
00003  *
00004  * This program is free software: you can redistribute it and/or modify
00005  * it under the terms of the GNU General Public License version 3 as
00006  * published by the Free Software Foundation.
00007  *
00008  * This program is distributed in the hope that it will be useful,
00009  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00010  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00011  * GNU General Public License for more details.
00012  *
00013  * You should have received a copy of the GNU General Public License
00014  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
00015  *
00016  * Authored by: Jason Smith <jason.smith@canonical.com>
00017  *
00018  */
00019 
00020 #include "bamf-application.h"
00021 #include "bamf-window.h"
00022 #include "bamf-legacy-screen.h"
00023 
00024 #define BAMF_WINDOW_GET_PRIVATE(obj) (G_TYPE_INSTANCE_GET_PRIVATE(obj, \
00025 BAMF_TYPE_WINDOW, BamfWindowPrivate))
00026 
00027 static void bamf_window_dbus_iface_init (BamfDBusItemWindowIface *iface);
00028 G_DEFINE_TYPE_WITH_CODE (BamfWindow, bamf_window, BAMF_TYPE_VIEW,
00029                          G_IMPLEMENT_INTERFACE (BAMF_DBUS_ITEM_TYPE_WINDOW,
00030                                                 bamf_window_dbus_iface_init));
00031 
00032 static GList *bamf_windows;
00033 
00034 enum
00035 {
00036   PROP_0,
00037 
00038   PROP_WINDOW,
00039 };
00040 
00041 struct _BamfWindowPrivate
00042 {
00043   BamfDBusItemWindow *dbus_iface;
00044   BamfLegacyWindow *legacy_window;
00045   BamfWindowMaximizationType maximized;
00046   gint monitor;
00047   gulong closed_id;
00048   gulong name_changed_id;
00049   gulong state_changed_id;
00050   gulong geometry_changed_id;
00051   time_t last_active;
00052   time_t opened;
00053 };
00054 
00055 BamfLegacyWindow *
00056 bamf_window_get_window (BamfWindow *self)
00057 {
00058   g_return_val_if_fail (BAMF_IS_WINDOW (self), NULL);
00059 
00060   if (BAMF_WINDOW_GET_CLASS (self)->get_window)
00061     return BAMF_WINDOW_GET_CLASS (self)->get_window (self);
00062 
00063   return self->priv->legacy_window;
00064 }
00065 
00066 BamfWindow *
00067 bamf_window_get_transient (BamfWindow *self)
00068 {
00069   BamfLegacyWindow *legacy, *transient;
00070   BamfWindow *other;
00071   GList *l;
00072   
00073   g_return_val_if_fail (BAMF_IS_WINDOW (self), NULL);
00074   
00075   legacy = bamf_window_get_window (self);
00076   transient = bamf_legacy_window_get_transient (legacy);
00077   
00078   if (transient)
00079     {
00080       for (l = bamf_windows; l; l = l->next)
00081         {
00082           other = l->data;
00083       
00084           if (!BAMF_IS_WINDOW (other))
00085             continue;
00086       
00087           if (transient == bamf_window_get_window (other))
00088             return other;
00089         }
00090     }
00091   return NULL;
00092 }
00093 
00094 const char *
00095 bamf_window_get_transient_path (BamfWindow *self)
00096 {
00097   BamfWindow *transient;
00098   
00099   g_return_val_if_fail (BAMF_IS_WINDOW (self), NULL);
00100   
00101   transient = bamf_window_get_transient (self);
00102   
00103   if (transient == NULL)
00104     return "";
00105   
00106   return bamf_view_get_path (BAMF_VIEW (transient));
00107 } 
00108 
00109 guint32
00110 bamf_window_get_window_type (BamfWindow *window)
00111 {
00112   g_return_val_if_fail (BAMF_IS_WINDOW (window), 0);
00113   
00114   return (guint32) bamf_legacy_window_get_window_type (window->priv->legacy_window);
00115 }
00116 
00117 guint32
00118 bamf_window_get_pid (BamfWindow *window)
00119 {
00120   g_return_val_if_fail (BAMF_IS_WINDOW (window), 0);
00121 
00122   return bamf_legacy_window_get_pid (window->priv->legacy_window);
00123 }
00124 
00125 guint32
00126 bamf_window_get_xid (BamfWindow *window)
00127 {
00128   g_return_val_if_fail (BAMF_IS_WINDOW (window), 0);
00129 
00130 
00131   if (BAMF_WINDOW_GET_CLASS (window)->get_xid)
00132     return BAMF_WINDOW_GET_CLASS (window)->get_xid (window);
00133 
00134   return (guint32) bamf_legacy_window_get_xid (window->priv->legacy_window);
00135 }
00136 
00137 time_t
00138 bamf_window_last_active (BamfWindow *self)
00139 {
00140   g_return_val_if_fail (BAMF_IS_WINDOW (self), (time_t) 0);
00141   
00142   if (bamf_view_is_active (BAMF_VIEW (self)))
00143     return time (NULL);
00144   return self->priv->last_active;
00145 }
00146 
00147 time_t
00148 bamf_window_opened (BamfWindow *self)
00149 {
00150   g_return_val_if_fail (BAMF_IS_WINDOW (self), (time_t) 0);
00151   
00152   return self->priv->opened;
00153 }
00154 
00155 static void
00156 handle_window_closed (BamfLegacyWindow * window, gpointer data)
00157 {
00158   BamfWindow *self;
00159   self = (BamfWindow *) data;
00160 
00161   g_return_if_fail (BAMF_IS_WINDOW (self));
00162   g_return_if_fail (BAMF_IS_LEGACY_WINDOW (window));
00163 
00164   if (window == self->priv->legacy_window)
00165     {
00166       bamf_view_close (BAMF_VIEW (self));
00167     }
00168 }
00169 
00170 static void
00171 handle_name_changed (BamfLegacyWindow *window, BamfWindow *self)
00172 {
00173   g_return_if_fail (BAMF_IS_LEGACY_WINDOW (window));
00174 
00175   bamf_view_set_name (BAMF_VIEW (self), bamf_legacy_window_get_name (window));
00176 }
00177 
00178 static void
00179 bamf_window_ensure_flags (BamfWindow *self)
00180 {
00181   g_return_if_fail (BAMF_IS_WINDOW (self));
00182 
00183   /* if we are going innactive, set our last active time */
00184   if (bamf_view_is_active (BAMF_VIEW (self)) && !bamf_legacy_window_is_active (self->priv->legacy_window))
00185     self->priv->last_active = time (NULL);
00186   
00187   bamf_view_set_active       (BAMF_VIEW (self), bamf_legacy_window_is_active (self->priv->legacy_window));
00188   bamf_view_set_urgent       (BAMF_VIEW (self), bamf_legacy_window_needs_attention (self->priv->legacy_window));
00189   bamf_view_set_user_visible (BAMF_VIEW (self), !bamf_legacy_window_is_skip_tasklist (self->priv->legacy_window));
00190 
00191   BamfWindowMaximizationType maximized = bamf_window_maximized (self);
00192 
00193   if (self->priv->maximized != maximized)
00194   {
00195     BamfWindowMaximizationType old_state = self->priv->maximized;
00196     self->priv->maximized = maximized;
00197     g_signal_emit_by_name (self, "maximized-changed", old_state, maximized);
00198   }
00199 }
00200 
00201 static void
00202 bamf_window_ensure_monitor (BamfWindow *self)
00203 {
00204   g_return_if_fail (BAMF_IS_WINDOW (self));
00205 
00206   gint monitor = bamf_window_get_monitor (self);
00207 
00208   if (self->priv->monitor != monitor)
00209   {
00210     gint old_monitor = self->priv->monitor;
00211     self->priv->monitor = monitor;
00212     g_signal_emit_by_name (self, "monitor-changed", old_monitor, monitor);
00213   }
00214 }
00215 
00216 static void
00217 handle_state_changed (BamfLegacyWindow *window, BamfWindow *self)
00218 {
00219   bamf_window_ensure_flags (self);
00220 }
00221 
00222 static void
00223 handle_geometry_changed (BamfLegacyWindow *window, BamfWindow *self)
00224 {
00225   bamf_window_ensure_monitor (self);
00226 }
00227 
00228 static const char *
00229 bamf_window_get_view_type (BamfView *view)
00230 {
00231   return "window";
00232 }
00233 
00234 char *
00235 bamf_window_get_xprop (BamfWindow *self, const char* prop)
00236 {
00237   g_return_val_if_fail (BAMF_IS_WINDOW (self), NULL);
00238   return bamf_legacy_window_get_utf8_xprop(self->priv->legacy_window, prop);
00239 }
00240 
00241 BamfWindowMaximizationType
00242 bamf_window_maximized (BamfWindow *self)
00243 {
00244   g_return_val_if_fail (BAMF_IS_WINDOW (self), BAMF_WINDOW_FLOATING);
00245   return bamf_legacy_window_maximized (self->priv->legacy_window);
00246 }
00247 
00248 gint
00249 bamf_window_get_monitor (BamfWindow *self)
00250 {
00251   gint x, y, width, height;
00252   g_return_val_if_fail (BAMF_IS_WINDOW (self), -1);
00253 
00254   GdkScreen *gdk_screen =  gdk_screen_get_default ();
00255   bamf_legacy_window_get_geometry (self->priv->legacy_window, &x, &y, &width, &height);
00256   
00257   return gdk_screen_get_monitor_at_point (gdk_screen, x + width/2, y + height/2);
00258 }
00259 
00260 char *
00261 bamf_window_get_stable_bus_name (BamfView *view)
00262 {
00263   BamfWindow *self;
00264 
00265   g_return_val_if_fail (BAMF_IS_WINDOW (view), NULL);  
00266   self = BAMF_WINDOW (view);
00267 
00268   return g_strdup_printf ("window%i", bamf_legacy_window_get_xid (self->priv->legacy_window));
00269 }
00270 
00271 gint
00272 bamf_window_get_stack_position (BamfWindow *self)
00273 {
00274   g_return_val_if_fail (BAMF_IS_WINDOW (self), -1);
00275 
00276   return bamf_legacy_window_get_stacking_position (self->priv->legacy_window);
00277 }
00278 
00279 static void
00280 active_window_changed (BamfLegacyScreen *screen, BamfWindow *window)
00281 {
00282   bamf_window_ensure_flags (window);
00283 }
00284 
00285 static gboolean
00286 on_dbus_handle_get_pid (BamfDBusItemWindow *interface,
00287                         GDBusMethodInvocation *invocation,
00288                         BamfWindow *self)
00289 {
00290   gint pid = bamf_window_get_pid (self);
00291   g_dbus_method_invocation_return_value (invocation, g_variant_new ("(u)", pid));
00292 
00293   return TRUE;
00294 }
00295 
00296 static gboolean
00297 on_dbus_handle_get_xid (BamfDBusItemWindow *interface,
00298                         GDBusMethodInvocation *invocation,
00299                         BamfWindow *self)
00300 {
00301   guint32 xid = bamf_window_get_xid (self);
00302   g_dbus_method_invocation_return_value (invocation, g_variant_new ("(u)", xid));
00303 
00304   return TRUE;
00305 }
00306 
00307 static gboolean
00308 on_dbus_handle_transient (BamfDBusItemWindow *interface,
00309                           GDBusMethodInvocation *invocation,
00310                           BamfWindow *self)
00311 {
00312   const char *transient_path = bamf_window_get_transient_path (self);
00313   g_dbus_method_invocation_return_value (invocation,
00314                                          g_variant_new ("(s)", transient_path));
00315 
00316   return TRUE;
00317 }
00318 
00319 static gboolean
00320 on_dbus_handle_window_type (BamfDBusItemWindow *interface,
00321                             GDBusMethodInvocation *invocation,
00322                             BamfWindow *self)
00323 {
00324   BamfWindowType window_type = bamf_window_get_window_type (self);
00325   g_dbus_method_invocation_return_value (invocation,
00326                                          g_variant_new ("(u)", window_type));
00327 
00328   return TRUE;
00329 }
00330 
00331 static gboolean
00332 on_dbus_handle_xprop (BamfDBusItemWindow *interface,
00333                       GDBusMethodInvocation *invocation,
00334                       const gchar *prop,
00335                       BamfWindow *self)
00336 {
00337   char *bus_name = bamf_window_get_xprop (self, prop);
00338   g_dbus_method_invocation_return_value (invocation,
00339                                          g_variant_new ("(s)", bus_name ? bus_name : ""));
00340 
00341   g_free (bus_name);
00342 
00343   return TRUE;
00344 }
00345 
00346 static gboolean
00347 on_dbus_handle_monitor (BamfDBusItemWindow *interface,
00348                         GDBusMethodInvocation *invocation,
00349                         BamfWindow *self)
00350 {
00351   gint monitor = bamf_window_get_monitor (self);
00352   g_dbus_method_invocation_return_value (invocation,
00353                                          g_variant_new ("(i)", monitor));
00354 
00355   return TRUE;
00356 }
00357 
00358 static gboolean
00359 on_dbus_handle_maximized (BamfDBusItemWindow *interface,
00360                           GDBusMethodInvocation *invocation,
00361                           BamfWindow *self)
00362 {
00363   BamfWindowMaximizationType maximized = bamf_window_maximized (self);
00364   g_dbus_method_invocation_return_value (invocation,
00365                                          g_variant_new ("(i)", maximized));
00366 
00367   return TRUE;
00368 }
00369 
00370 static void
00371 bamf_window_set_property (GObject *object, guint property_id, const GValue *value, GParamSpec *pspec)
00372 {
00373   BamfWindow *self;
00374 
00375   self = BAMF_WINDOW (object);
00376 
00377   switch (property_id)
00378     {
00379       case PROP_WINDOW:
00380         self->priv->legacy_window = BAMF_LEGACY_WINDOW (g_value_get_object (value));
00381         break;
00382 
00383       default:
00384         G_OBJECT_WARN_INVALID_PROPERTY_ID(object, property_id, pspec);
00385     }
00386 }
00387 
00388 static void
00389 bamf_window_get_property (GObject *object, guint property_id, GValue *value, GParamSpec *pspec)
00390 {
00391   BamfWindow *self;
00392 
00393   self = BAMF_WINDOW (object);
00394 
00395   switch (property_id)
00396     {
00397       case PROP_WINDOW:
00398         g_value_set_object (value, self->priv->legacy_window);
00399 
00400         break;
00401 
00402       default:
00403         G_OBJECT_WARN_INVALID_PROPERTY_ID(object, property_id, pspec);
00404     }
00405 }
00406 
00407 static void
00408 on_maximized_changed (BamfWindow *self, BamfWindowMaximizationType old,
00409                       BamfWindowMaximizationType new, gpointer _not_used)
00410 {
00411   g_return_if_fail (BAMF_IS_WINDOW (self));
00412   g_signal_emit_by_name (self->priv->dbus_iface, "maximized-changed", old, new);
00413 }
00414 
00415 static void
00416 on_monitor_changed (BamfWindow *self, gint old, gint new, gpointer _not_used)
00417 {
00418   g_return_if_fail (BAMF_IS_WINDOW (self));
00419   g_signal_emit_by_name (self->priv->dbus_iface, "monitor-changed", old, new);
00420 }
00421 
00422 static void
00423 bamf_window_constructed (GObject *object)
00424 {
00425   BamfWindow *self;
00426   BamfLegacyWindow *window;
00427 
00428   if (G_OBJECT_CLASS (bamf_window_parent_class)->constructed)
00429     G_OBJECT_CLASS (bamf_window_parent_class)->constructed (object);
00430 
00431   g_object_get (object, "legacy-window", &window, NULL);
00432 
00433   self = BAMF_WINDOW (object);
00434   bamf_windows = g_list_prepend (bamf_windows, self);
00435 
00436   self->priv->opened = time (NULL);
00437 
00438   bamf_view_set_name (BAMF_VIEW (self), bamf_legacy_window_get_name (window));
00439 
00440   self->priv->name_changed_id = g_signal_connect (G_OBJECT (window), "name-changed",
00441                                                   (GCallback) handle_name_changed, self);
00442 
00443   self->priv->state_changed_id = g_signal_connect (G_OBJECT (window), "state-changed",
00444                                                    (GCallback) handle_state_changed, self);
00445 
00446   self->priv->geometry_changed_id = g_signal_connect (G_OBJECT (window), "geometry-changed",
00447                                                       (GCallback) handle_geometry_changed, self);
00448 
00449   self->priv->closed_id = g_signal_connect (G_OBJECT (window), "closed",
00450                                             (GCallback) handle_window_closed, self);
00451 
00452   self->priv->maximized = -1;
00453   self->priv->monitor = -1;
00454 
00455   bamf_window_ensure_flags (self);
00456   bamf_window_ensure_monitor (self);
00457 }
00458 
00459 static void
00460 bamf_window_dispose (GObject *object)
00461 {
00462   BamfWindow *self;
00463 
00464   self = BAMF_WINDOW (object);
00465   bamf_windows = g_list_remove (bamf_windows, self);
00466 
00467   g_signal_handlers_disconnect_by_func (bamf_legacy_screen_get_default (),
00468                                         active_window_changed, self);
00469 
00470   if (self->priv->legacy_window)
00471     {
00472       g_signal_handler_disconnect (self->priv->legacy_window,
00473                                    self->priv->name_changed_id);
00474 
00475       g_signal_handler_disconnect (self->priv->legacy_window,
00476                                    self->priv->state_changed_id);
00477 
00478       g_signal_handler_disconnect (self->priv->legacy_window,
00479                                    self->priv->geometry_changed_id);
00480 
00481       g_signal_handler_disconnect (self->priv->legacy_window,
00482                                    self->priv->closed_id);
00483 
00484       g_object_unref (self->priv->legacy_window);
00485       self->priv->legacy_window = NULL;
00486     }
00487   G_OBJECT_CLASS (bamf_window_parent_class)->dispose (object);
00488 }
00489 
00490 static void
00491 bamf_window_finalize (GObject *object)
00492 {
00493   BamfWindow *self;
00494   self = BAMF_WINDOW (object);
00495 
00496   g_object_unref (self->priv->dbus_iface);
00497 
00498   G_OBJECT_CLASS (bamf_window_parent_class)->finalize (object);
00499 }
00500 
00501 static void
00502 bamf_window_init (BamfWindow * self)
00503 {
00504   self->priv = BAMF_WINDOW_GET_PRIVATE (self);
00505 
00506   /* Initializing the dbus interface */
00507   self->priv->dbus_iface = bamf_dbus_item_window_skeleton_new ();
00508 
00509   /* We need to connect to the object own signals to redirect them to the dbus
00510    * interface                                                                */
00511   g_signal_connect (self, "maximized-changed", G_CALLBACK (on_maximized_changed), NULL);
00512   g_signal_connect (self, "monitor-changed", G_CALLBACK (on_monitor_changed), NULL);
00513 
00514   /* Registering signal callbacks to reply to dbus method calls */
00515   g_signal_connect (self->priv->dbus_iface, "handle-get-pid",
00516                     G_CALLBACK (on_dbus_handle_get_pid), self);
00517 
00518   g_signal_connect (self->priv->dbus_iface, "handle-get-xid",
00519                     G_CALLBACK (on_dbus_handle_get_xid), self);
00520 
00521   g_signal_connect (self->priv->dbus_iface, "handle-transient",
00522                     G_CALLBACK (on_dbus_handle_transient), self);
00523 
00524   g_signal_connect (self->priv->dbus_iface, "handle-window-type",
00525                     G_CALLBACK (on_dbus_handle_window_type), self);
00526 
00527   g_signal_connect (self->priv->dbus_iface, "handle-xprop",
00528                     G_CALLBACK (on_dbus_handle_xprop), self);
00529 
00530   g_signal_connect (self->priv->dbus_iface, "handle-monitor",
00531                     G_CALLBACK (on_dbus_handle_monitor), self);
00532 
00533   g_signal_connect (self->priv->dbus_iface, "handle-maximized",
00534                     G_CALLBACK (on_dbus_handle_maximized), self);
00535 
00536   /* Setting the interface for the dbus object */
00537   bamf_dbus_item_object_skeleton_set_window (BAMF_DBUS_ITEM_OBJECT_SKELETON (self),
00538                                              self->priv->dbus_iface);
00539 
00540   g_signal_connect (G_OBJECT (bamf_legacy_screen_get_default ()), "active-window-changed",
00541                     (GCallback) active_window_changed, self);
00542 }
00543 
00544 static void
00545 bamf_window_dbus_iface_init (BamfDBusItemWindowIface *iface)
00546 {
00547 }
00548 
00549 static void
00550 bamf_window_class_init (BamfWindowClass * klass)
00551 {
00552   GParamSpec *pspec;
00553   GObjectClass *object_class = G_OBJECT_CLASS (klass);
00554   BamfViewClass *view_class = BAMF_VIEW_CLASS (klass);
00555 
00556   object_class->dispose       = bamf_window_dispose;
00557   object_class->finalize      = bamf_window_finalize;
00558   object_class->get_property  = bamf_window_get_property;
00559   object_class->set_property  = bamf_window_set_property;
00560   object_class->constructed   = bamf_window_constructed;
00561   view_class->view_type       = bamf_window_get_view_type;
00562   view_class->stable_bus_name = bamf_window_get_stable_bus_name;
00563 
00564   pspec = g_param_spec_object ("legacy-window", "legacy-window", "legacy-window",
00565                                BAMF_TYPE_LEGACY_WINDOW,
00566                                G_PARAM_READWRITE | G_PARAM_CONSTRUCT);
00567   g_object_class_install_property (object_class, PROP_WINDOW, pspec);
00568 
00569   g_type_class_add_private (klass, sizeof (BamfWindowPrivate));
00570 }
00571 
00572 BamfWindow *
00573 bamf_window_new (BamfLegacyWindow *window)
00574 {
00575   BamfWindow *self;
00576   self = (BamfWindow *) g_object_new (BAMF_TYPE_WINDOW, "legacy-window", window, NULL);
00577   
00578   return self;
00579 }