1 /*
2 * Copyright 2010 Canonical Ltd.
3 *
4 * This program is free software: you can redistribute it and/or modify it
5 * under the terms of either or both of the following licenses:
6 *
7 * 1) the GNU Lesser General Public License version 3, as published by the
8 * Free Software Foundation; and/or
9 * 2) the GNU Lesser General Public License version 2.1, as published by
10 * the Free Software Foundation.
11 *
12 * This program is distributed in the hope that it will be useful, but
13 * WITHOUT ANY WARRANTY; without even the implied warranties of
14 * MERCHANTABILITY, SATISFACTORY QUALITY or FITNESS FOR A PARTICULAR
15 * PURPOSE. See the applicable version of the GNU Lesser General Public
16 * License for more details.
17 *
18 * You should have received a copy of both the GNU Lesser General Public
19 * License version 3 and version 2.1 along with this program. If not, see
20 * <http://www.gnu.org/licenses/>
21 *
22 * Authored by: Jason Smith <jason.smith@canonical.com>
23 * Neil Jagdish Patel <neil.patel@canonical.com>
24 *
25 */
26 /**
27 * SECTION:bamf-view
28 * @short_description: The base class for all views
29 *
30 * #BamfView is the base class that all views need to derive from.
31 */
32
33 #if HAVE_CONFIG_H
34 #include <config.h>
35 #endif
36
37 #include "bamf-view.h"
38 #include "bamf-view-private.h"
39 #include "bamf-factory.h"
40 #include "bamf-window.h"
41 #include "bamf-marshal.h"
42
43 #include <dbus/dbus.h>
44 #include <dbus/dbus-glib.h>
45 #include <dbus/dbus-glib-lowlevel.h>
46
47 G_DEFINE_TYPE (BamfView, bamf_view, G_TYPE_INITIALLY_UNOWNED);
48
49 #define BAMF_VIEW_GET_PRIVATE(o) \
50 (G_TYPE_INSTANCE_GET_PRIVATE ((o), BAMF_TYPE_VIEW, BamfViewPrivate))
51
52 enum
53 {
54 BAMF_VIEW_RUNNING_FLAG = 1 << 0,
55 BAMF_VIEW_URGENT_FLAG = 1 << 1,
56 BAMF_VIEW_VISIBLE_FLAG = 1 << 2,
57 BAMF_VIEW_ACTIVE_FLAG = 1 << 3,
58 };
59
60 enum
61 {
62 ACTIVE_CHANGED,
63 CLOSED,
64 CHILD_ADDED,
65 CHILD_REMOVED,
66 RUNNING_CHANGED,
67 URGENT_CHANGED,
68 VISIBLE_CHANGED,
69 NAME_CHANGED,
70
71 LAST_SIGNAL,
72 };
73
74 enum
75 {
76 PROP_0,
77
78 PROP_PATH,
79 PROP_RUNNING,
80 PROP_ACTIVE,
81 PROP_USER_VISIBLE,
82 PROP_URGENT,
83 };
84
85 static guint view_signals[LAST_SIGNAL] = { 0 };
86
87 struct _BamfViewPrivate
88 {
89 DBusGConnection *connection;
90 DBusGProxy *proxy;
91 gchar *path;
92 gchar *type;
93 gchar *local_icon;
94 gchar *local_name;
95 guint checked_flags;
96 guint set_flags;
97 gboolean is_closed;
98 gboolean sticky;
99 GList *cached_children;
100 };
101
102 static void
103 bamf_view_set_flag (BamfView *view, guint flag, gboolean value)
104 {
105 BamfViewPrivate *priv;
106
107 g_return_if_fail (BAMF_IS_VIEW (view));
108
109 priv = view->priv;
110
111 if (value)
112 priv->set_flags |= flag;
113 else
114 priv->set_flags = priv->set_flags & ~flag;
115
116 priv->checked_flags |= flag;
117 }
118
119 static gboolean
120 bamf_view_flag_is_set (BamfView *view, guint flag)
121 {
122 BamfViewPrivate *priv;
123
124 g_return_val_if_fail (BAMF_IS_VIEW (view), FALSE);
125
126 priv = view->priv;
127
128 return priv->checked_flags & flag;
129 }
130
131 static gboolean
132 bamf_view_get_flag (BamfView *view, guint flag)
133 {
134 BamfViewPrivate *priv;
135
136 g_return_val_if_fail (BAMF_IS_VIEW (view), FALSE);
137
138 priv = view->priv;
139
140 return priv->set_flags & flag;
141 }
142
143 GList *
144 bamf_view_get_children (BamfView *view)
145 {
146 char ** children;
147 int i, len;
148 GList *results = NULL;
149 GError *error = NULL;
150 BamfViewPrivate *priv;
151
152 g_return_val_if_fail (BAMF_IS_VIEW (view), NULL);
153
154 if (BAMF_VIEW_GET_CLASS (view)->get_children)
155 return BAMF_VIEW_GET_CLASS (view)->get_children (view);
156
157 if (!bamf_view_remote_ready (view))
158 return NULL;
159
160 priv = view->priv;
161
162 if (priv->cached_children)
163 return g_list_copy (priv->cached_children);
164
165 if (!dbus_g_proxy_call (priv->proxy,
166 "Children",
167 &error,
168 G_TYPE_INVALID,
169 G_TYPE_STRV, &children,
170 G_TYPE_INVALID))
171 {
172 g_warning ("Unable to fetch children: %s\n", error->message);
173 g_error_free (error);
174 return NULL;
175 }
176
177 if (!children)
178 return NULL;
179
180 len = g_strv_length (children);
181
182 for (i = len-1; i >= 0; i--)
183 {
CID 10449 - PW.PARAMETER_HIDDEN
declaration hides parameter "view" (declared at line 144)
184 BamfView *view = bamf_factory_view_for_path (bamf_factory_get_default (), children[i]);
185 results = g_list_prepend (results, g_object_ref (view));
186 }
187
188 priv->cached_children = results;
189 return g_list_copy (priv->cached_children);
190 }
191
192 static gboolean
193 bamf_view_get_boolean (BamfView *self, const char *method_name, guint flag)
194 {
195 BamfViewPrivate *priv;
196 gboolean result = FALSE;
197 GError *error = NULL;
198
199 g_return_val_if_fail (BAMF_IS_VIEW (self), FALSE);
200 priv = self->priv;
201
202 if (bamf_view_flag_is_set (self, flag))
203 return bamf_view_get_flag (self, flag);
204
205 if (!bamf_view_remote_ready (self))
206 return FALSE;
207
208 if (!dbus_g_proxy_call (priv->proxy,
209 method_name,
210 &error,
211 G_TYPE_INVALID,
212 G_TYPE_BOOLEAN, &result,
213 G_TYPE_INVALID))
214 {
215 g_warning ("Failed to fetch boolean: %s", error->message);
216 g_error_free (error);
217
218 return FALSE;
219 }
220
221 bamf_view_set_flag (self, flag, result);
222 return result;
223 }
224
225 gboolean
226 bamf_view_is_closed (BamfView *view)
227 {
228 g_return_val_if_fail (BAMF_IS_VIEW (view), TRUE);
229
230 return view->priv->is_closed;
231 }
232
233 gboolean
234 bamf_view_is_active (BamfView *view)
235 {
236 g_return_val_if_fail (BAMF_IS_VIEW (view), FALSE);
237
238 if (BAMF_VIEW_GET_CLASS (view)->is_active)
239 return BAMF_VIEW_GET_CLASS (view)->is_active (view);
240
241 return bamf_view_get_boolean (view, "IsActive", BAMF_VIEW_ACTIVE_FLAG);
242
243 }
244
245 gboolean
246 bamf_view_user_visible (BamfView *self)
247 {
248 g_return_val_if_fail (BAMF_IS_VIEW (self), FALSE);
249
250 return bamf_view_get_boolean (self, "UserVisible", BAMF_VIEW_VISIBLE_FLAG);
251
252 }
253
254 gboolean
255 bamf_view_is_running (BamfView *self)
256 {
257 g_return_val_if_fail (BAMF_IS_VIEW (self), FALSE);
258
259 if (BAMF_VIEW_GET_CLASS (self)->is_running)
260 return BAMF_VIEW_GET_CLASS (self)->is_running (self);
261
262 return bamf_view_get_boolean (self, "IsRunning", BAMF_VIEW_RUNNING_FLAG);
263 }
264
265 gboolean
266 bamf_view_is_urgent (BamfView *self)
267 {
268 g_return_val_if_fail (BAMF_IS_VIEW (self), FALSE);
269
270 if (BAMF_VIEW_GET_CLASS (self)->is_urgent)
271 return BAMF_VIEW_GET_CLASS (self)->is_urgent (self);
272
273 return bamf_view_get_boolean (self, "IsUrgent", BAMF_VIEW_URGENT_FLAG);
274 }
275
276 void
277 bamf_view_set_name (BamfView *view, const char *name)
278 {
279 g_return_if_fail (BAMF_IS_VIEW (view));
280
281 if (!g_strcmp0 (name, view->priv->local_name))
282 return;
283
284 g_free (view->priv->local_name);
285
286 if (name && name[0] == '\0')
287 {
288 view->priv->local_name = NULL;
289 }
290 else
291 {
292 view->priv->local_name = g_strdup (name);
293 }
294 }
295
296 void
297 bamf_view_set_icon (BamfView *view, const char *icon)
298 {
299 g_return_if_fail (BAMF_IS_VIEW (view));
300
301 g_free (view->priv->local_icon);
302
303 if (icon && icon[0] == '\0')
304 {
305 view->priv->local_icon = NULL;
306 }
307 else
308 {
309 view->priv->local_icon = g_strdup (icon);
310 }
311 }
312
313 gboolean
314 bamf_view_is_sticky (BamfView *view)
315 {
316 g_return_val_if_fail (BAMF_IS_VIEW (view), FALSE);
317
318 return view->priv->sticky;
319 }
320
321 void
322 bamf_view_set_sticky (BamfView *view, gboolean value)
323 {
324 g_return_if_fail (BAMF_IS_VIEW (view));
325
326 if (value == view->priv->sticky)
327 return;
328
329 view->priv->sticky = value;
330
331 if (value)
332 g_object_ref_sink (view);
333 else
334 g_object_unref (view);
335 }
336
337 gchar *
338 bamf_view_get_icon (BamfView *self)
339 {
340 BamfViewPrivate *priv;
341 char *icon = NULL;
342 GError *error = NULL;
343
344 g_return_val_if_fail (BAMF_IS_VIEW (self), NULL);
345 priv = self->priv;
346
347 if (BAMF_VIEW_GET_CLASS (self)->get_icon)
348 return BAMF_VIEW_GET_CLASS (self)->get_icon (self);
349
350 if (!bamf_view_remote_ready (self))
351 return g_strdup (priv->local_icon);
352
353 if (!dbus_g_proxy_call (priv->proxy,
354 "Icon",
355 &error,
356 G_TYPE_INVALID,
357 G_TYPE_STRING, &icon,
358 G_TYPE_INVALID))
359 {
360 g_warning ("Failed to fetch icon: %s", error->message);
361 g_error_free (error);
362
363 return NULL;
364 }
365
366 if (icon && icon[0] == '\0')
367 {
368 g_free (icon);
369 return NULL;
370 }
371
372 return icon;
373 }
374
375 gchar *
376 bamf_view_get_name (BamfView *self)
377 {
378 BamfViewPrivate *priv;
379 char *name = NULL;
380 GError *error = NULL;
381
382 g_return_val_if_fail (BAMF_IS_VIEW (self), NULL);
383 priv = self->priv;
384
385 if (BAMF_VIEW_GET_CLASS (self)->get_name)
386 return BAMF_VIEW_GET_CLASS (self)->get_name (self);
387
388 if (!bamf_view_remote_ready (self))
389 return g_strdup(priv->local_name);
390
391 if (!dbus_g_proxy_call (priv->proxy,
392 "Name",
393 &error,
394 G_TYPE_INVALID,
395 G_TYPE_STRING, &name,
396 G_TYPE_INVALID))
397 {
398 g_warning ("Failed to fetch name: %s", error->message);
399 g_error_free (error);
400
401 return NULL;
402 }
403
404 if (name && name[0] == '\0')
405 {
406 g_free (name);
407 return NULL;
408 }
409
410 return name;
411 }
412
413 gboolean
414 bamf_view_remote_ready (BamfView *view)
415 {
416 return BAMF_IS_VIEW (view) && view->priv->proxy;
417 }
418
419 const gchar *
420 bamf_view_get_view_type (BamfView *self)
421 {
422 BamfViewPrivate *priv;
423 char *type = NULL;
424 GError *error = NULL;
425
426 g_return_val_if_fail (BAMF_IS_VIEW (self), NULL);
427 priv = self->priv;
428
429 if (BAMF_VIEW_GET_CLASS (self)->view_type)
430 return BAMF_VIEW_GET_CLASS (self)->view_type (self);
431
432 if (priv->type)
433 return priv->type;
434
435 if (!dbus_g_proxy_call (priv->proxy,
436 "ViewType",
437 &error,
438 G_TYPE_INVALID,
439 G_TYPE_STRING, &type,
440 G_TYPE_INVALID))
441 {
442 g_warning ("Failed to fetch view type at %s: %s", dbus_g_proxy_get_path (priv->proxy), error->message);
443 g_error_free (error);
444 return NULL;
445 }
446
447 priv->type = type;
448 return type;
449 }
450
451 BamfClickBehavior
452 bamf_view_get_click_suggestion (BamfView *self)
453 {
454 g_return_val_if_fail (BAMF_IS_VIEW (self), BAMF_CLICK_BEHAVIOR_NONE);
455
456 if (BAMF_VIEW_GET_CLASS (self)->click_behavior)
457 return BAMF_VIEW_GET_CLASS (self)->click_behavior (self);
458
459 return BAMF_CLICK_BEHAVIOR_NONE;
460 }
461
462 static void
463 bamf_view_on_child_added (DBusGProxy *proxy, char *path, BamfView *self)
464 {
465 BamfView *view;
466 BamfViewPrivate *priv;
467
468 view = bamf_factory_view_for_path (bamf_factory_get_default (), path);
469 priv = self->priv;
470
471 if (priv->cached_children)
472 {
473 g_list_free_full (priv->cached_children, g_object_unref);
474 priv->cached_children = NULL;
475 }
476
477 g_signal_emit (G_OBJECT (self), view_signals[CHILD_ADDED], 0, view);
478 }
479
480 static void
481 bamf_view_on_child_removed (DBusGProxy *proxy, char *path, BamfView *self)
482 {
483 BamfView *view;
484 BamfViewPrivate *priv;
485 view = bamf_factory_view_for_path (bamf_factory_get_default (), path);
486 priv = self->priv;
487
488 if (priv->cached_children)
489 {
490 g_list_free_full (priv->cached_children, g_object_unref);
491 priv->cached_children = NULL;
492 }
493
494 g_signal_emit (G_OBJECT (self), view_signals[CHILD_REMOVED], 0, view);
495 }
496
497 static void
498 bamf_view_on_active_changed (DBusGProxy *proxy, gboolean active, BamfView *self)
499 {
500 bamf_view_set_flag (self, BAMF_VIEW_ACTIVE_FLAG, active);
501
502 g_signal_emit (G_OBJECT(self), view_signals[ACTIVE_CHANGED], 0, active);
503 g_object_notify (G_OBJECT (self), "active");
504 }
505
506 static void
507 bamf_view_on_name_changed (DBusGProxy* proxy,
508 const gchar* old_name,
509 const gchar* new_name,
510 BamfView* self)
511 {
512 g_free (self->priv->local_name);
513 self->priv->local_name = g_strdup (new_name);
514
515 g_signal_emit (self, view_signals[NAME_CHANGED], 0, old_name, new_name);
516 }
517
518 static void
519 bamf_view_on_running_changed (DBusGProxy *proxy, gboolean running, BamfView *self)
520 {
521 bamf_view_set_flag (self, BAMF_VIEW_RUNNING_FLAG, running);
522
523 g_signal_emit (G_OBJECT (self), view_signals[RUNNING_CHANGED], 0, running);
524 g_object_notify (G_OBJECT (self), "running");
525 }
526
527 static void
528 bamf_view_on_urgent_changed (DBusGProxy *proxy, gboolean urgent, BamfView *self)
529 {
530 bamf_view_set_flag (self, BAMF_VIEW_URGENT_FLAG, urgent);
531
532 g_signal_emit (G_OBJECT (self), view_signals[URGENT_CHANGED], 0, urgent);
533 g_object_notify (G_OBJECT (self), "urgent");
534 }
535
536 static void
537 bamf_view_on_user_visible_changed (DBusGProxy *proxy, gboolean visible, BamfView *self)
538 {
539 bamf_view_set_flag (self, BAMF_VIEW_VISIBLE_FLAG, visible);
540
541 g_signal_emit (G_OBJECT (self), view_signals[VISIBLE_CHANGED], 0, visible);
542 g_object_notify (G_OBJECT (self), "user-visible");
543 }
544
545 static void
546 bamf_view_on_closed (DBusGProxy *proxy, BamfView *self)
547 {
548 BamfViewPrivate *priv;
549
550 priv = self->priv;
551
552 priv->is_closed = TRUE;
553
554 if (priv->cached_children)
555 {
556 g_list_free_full (priv->cached_children, g_object_unref);
557 priv->cached_children = NULL;
558 }
559
560 if (priv->sticky && priv->proxy)
561 {
562 dbus_g_proxy_disconnect_signal (priv->proxy,
563 "ActiveChanged",
564 (GCallback) bamf_view_on_active_changed,
565 self);
566
567 dbus_g_proxy_disconnect_signal (priv->proxy,
568 "Closed",
569 (GCallback) bamf_view_on_closed,
570 self);
571
572 dbus_g_proxy_disconnect_signal (priv->proxy,
573 "ChildAdded",
574 (GCallback) bamf_view_on_child_added,
575 self);
576
577 dbus_g_proxy_disconnect_signal (priv->proxy,
578 "ChildRemoved",
579 (GCallback) bamf_view_on_child_removed,
580 self);
581
582 dbus_g_proxy_disconnect_signal (priv->proxy,
583 "RunningChanged",
584 (GCallback) bamf_view_on_running_changed,
585 self);
586
587 dbus_g_proxy_disconnect_signal (priv->proxy,
588 "UrgentChanged",
589 (GCallback) bamf_view_on_urgent_changed,
590 self);
591
592 dbus_g_proxy_disconnect_signal (priv->proxy,
593 "UserVisibleChanged",
594 (GCallback) bamf_view_on_user_visible_changed,
595 self);
596 g_object_unref (priv->proxy);
597 priv->proxy = NULL;
598 }
599
600 g_object_ref (self);
601
602 // must be emitted before path is cleared as path is utilized in cleanup
603 g_signal_emit (G_OBJECT (self), view_signals[CLOSED], 0);
604
605 if (priv->path)
606 {
607 g_free (priv->path);
608 priv->path = NULL;
609 }
610
611 g_object_unref (self);
612 }
613
614 static void
615 bamf_view_set_property (GObject *object, guint property_id, const GValue *value, GParamSpec *pspec)
616 {
617 switch (property_id)
618 {
619 default:
620 G_OBJECT_WARN_INVALID_PROPERTY_ID(object, property_id, pspec);
621 }
622 }
623
624 static void
625 bamf_view_get_property (GObject *object, guint property_id, GValue *value, GParamSpec *pspec)
626 {
627 BamfView *self;
628
629 self = BAMF_VIEW (object);
630
631 switch (property_id)
632 {
633 case PROP_PATH:
634 g_value_set_string (value, self->priv->path);
635 break;
636
637 case PROP_ACTIVE:
638 g_value_set_boolean (value, bamf_view_is_active (self));
639 break;
640
641 case PROP_RUNNING:
642 g_value_set_boolean (value, bamf_view_is_running (self));
643 break;
644
645 case PROP_URGENT:
646 g_value_set_boolean (value, bamf_view_is_urgent (self));
647 break;
648
649 case PROP_USER_VISIBLE:
650 g_value_set_boolean (value, bamf_view_user_visible (self));
651 break;
652
653 default:
654 G_OBJECT_WARN_INVALID_PROPERTY_ID(object, property_id, pspec);
655 }
656 }
657
658 static void
659 bamf_view_dispose (GObject *object)
660 {
661 BamfView *view;
662 BamfViewPrivate *priv;
663
664 view = BAMF_VIEW (object);
665
666 priv = view->priv;
667
668 if (priv->path)
669 {
670 g_free (priv->path);
671 priv->path = NULL;
672 }
673
674 if (priv->type)
675 {
676 g_free (priv->type);
677 priv->type = NULL;
678 }
679
680 if (priv->cached_children)
681 {
682 g_list_free_full (priv->cached_children, g_object_unref);
683 priv->cached_children = NULL;
684 }
685
686 if (priv->proxy)
687 {
688 dbus_g_proxy_disconnect_signal (priv->proxy,
689 "ActiveChanged",
690 (GCallback) bamf_view_on_active_changed,
691 view);
692
693 dbus_g_proxy_disconnect_signal (priv->proxy,
694 "Closed",
695 (GCallback) bamf_view_on_closed,
696 view);
697
698 dbus_g_proxy_disconnect_signal (priv->proxy,
699 "ChildAdded",
700 (GCallback) bamf_view_on_child_added,
701 view);
702
703 dbus_g_proxy_disconnect_signal (priv->proxy,
704 "ChildRemoved",
705 (GCallback) bamf_view_on_child_removed,
706 view);
707
708 dbus_g_proxy_disconnect_signal (priv->proxy,
709 "RunningChanged",
710 (GCallback) bamf_view_on_running_changed,
711 view);
712
713 dbus_g_proxy_disconnect_signal (priv->proxy,
714 "UrgentChanged",
715 (GCallback) bamf_view_on_urgent_changed,
716 view);
717
718 dbus_g_proxy_disconnect_signal (priv->proxy,
719 "UserVisibleChanged",
720 (GCallback) bamf_view_on_user_visible_changed,
721 view);
722
723 dbus_g_proxy_disconnect_signal (priv->proxy,
724 "NameChanged",
725 (GCallback) bamf_view_on_name_changed,
726 view);
727
728 g_object_unref (priv->proxy);
729 priv->proxy = NULL;
730 }
731 }
732
733 const char *
734 bamf_view_get_path (BamfView *view)
735 {
736 g_return_val_if_fail (BAMF_IS_VIEW (view), NULL);
737
738 return view->priv->path;
739 }
740
741 void
742 bamf_view_set_path (BamfView *view, const char *path)
743 {
744 BamfViewPrivate *priv;
745
746 g_return_if_fail (BAMF_IS_VIEW (view));
747
748 priv = view->priv;
749 priv->is_closed = FALSE;
750
751 if (priv->path)
752 {
753 g_free (priv->path);
754 }
755
756 priv->path = g_strdup (path);
757 priv->proxy = dbus_g_proxy_new_for_name (priv->connection,
758 "org.ayatana.bamf",
759 priv->path,
760 "org.ayatana.bamf.view");
761 if (priv->proxy == NULL)
762 {
763 g_critical ("Unable to get org.ayatana.bamf.view view");
764 return;
765 }
766
767 dbus_g_proxy_add_signal (priv->proxy,
768 "ActiveChanged",
769 G_TYPE_BOOLEAN,
770 G_TYPE_INVALID);
771
772 dbus_g_proxy_add_signal (priv->proxy,
773 "Closed",
774 G_TYPE_INVALID);
775
776 dbus_g_proxy_add_signal (priv->proxy,
777 "ChildAdded",
778 G_TYPE_STRING,
779 G_TYPE_INVALID);
780
781 dbus_g_proxy_add_signal (priv->proxy,
782 "ChildRemoved",
783 G_TYPE_STRING,
784 G_TYPE_INVALID);
785
786 dbus_g_proxy_add_signal (priv->proxy,
787 "RunningChanged",
788 G_TYPE_BOOLEAN,
789 G_TYPE_INVALID);
790
791 dbus_g_proxy_add_signal (priv->proxy,
792 "UrgentChanged",
793 G_TYPE_BOOLEAN,
794 G_TYPE_INVALID);
795
796 dbus_g_proxy_add_signal (priv->proxy,
797 "UserVisibleChanged",
798 G_TYPE_BOOLEAN,
799 G_TYPE_INVALID);
800
801 dbus_g_proxy_add_signal (priv->proxy,
802 "NameChanged",
803 G_TYPE_STRING,
804 G_TYPE_STRING,
805 G_TYPE_INVALID);
806
807 dbus_g_proxy_connect_signal (priv->proxy,
808 "ActiveChanged",
809 (GCallback) bamf_view_on_active_changed,
810 view,
811 NULL);
812
813 dbus_g_proxy_connect_signal (priv->proxy,
814 "Closed",
815 (GCallback) bamf_view_on_closed,
816 view,
817 NULL);
818
819 dbus_g_proxy_connect_signal (priv->proxy,
820 "ChildAdded",
821 (GCallback) bamf_view_on_child_added,
822 view,
823 NULL);
824
825 dbus_g_proxy_connect_signal (priv->proxy,
826 "ChildRemoved",
827 (GCallback) bamf_view_on_child_removed,
828 view,
829 NULL);
830
831 dbus_g_proxy_connect_signal (priv->proxy,
832 "RunningChanged",
833 (GCallback) bamf_view_on_running_changed,
834 view,
835 NULL);
836
837 dbus_g_proxy_connect_signal (priv->proxy,
838 "UrgentChanged",
839 (GCallback) bamf_view_on_urgent_changed,
840 view,
841 NULL);
842
843 dbus_g_proxy_connect_signal (priv->proxy,
844 "UserVisibleChanged",
845 (GCallback) bamf_view_on_user_visible_changed,
846 view,
847 NULL);
848
849 dbus_g_proxy_connect_signal (priv->proxy,
850 "NameChanged",
851 (GCallback) bamf_view_on_name_changed,
852 view,
853 NULL);
854
855 if (bamf_view_is_sticky (view))
856 {
857 priv->checked_flags = 0x0;
858
859 if (bamf_view_user_visible (view))
860 {
861 g_signal_emit (G_OBJECT(view), view_signals[VISIBLE_CHANGED], 0, TRUE);
862 g_object_notify (G_OBJECT (view), "user-visible");
863 }
864
865 if (bamf_view_is_active (view))
866 {
867 g_signal_emit (G_OBJECT(view), view_signals[ACTIVE_CHANGED], 0, TRUE);
868 g_object_notify (G_OBJECT (view), "active");
869 }
870
871 if (bamf_view_is_running (view))
872 {
873 g_signal_emit (G_OBJECT(view), view_signals[RUNNING_CHANGED], 0, TRUE);
874 g_object_notify (G_OBJECT (view), "running");
875 }
876
877 if (bamf_view_is_urgent (view))
878 {
879 g_signal_emit (G_OBJECT(view), view_signals[URGENT_CHANGED], 0, TRUE);
880 g_object_notify (G_OBJECT (view), "urgent");
881 }
882 }
883 if (BAMF_VIEW_GET_CLASS (view)->set_path)
884 BAMF_VIEW_GET_CLASS (view)->set_path (view, path);
885 }
886
887 static void
888 bamf_view_constructed (GObject *object)
889 {
890 if (G_OBJECT_CLASS (bamf_view_parent_class)->constructed)
891 G_OBJECT_CLASS (bamf_view_parent_class)->constructed (object);
892 }
893
894 static void
895 bamf_view_class_init (BamfViewClass *klass)
896 {
897 GParamSpec *pspec;
898 GObjectClass *obj_class = G_OBJECT_CLASS (klass);
899
900 obj_class->constructed = bamf_view_constructed;
901 obj_class->dispose = bamf_view_dispose;
902 obj_class->get_property = bamf_view_get_property;
903 obj_class->set_property = bamf_view_set_property;
904
905 pspec = g_param_spec_string ("path", "path", "path", NULL, G_PARAM_READABLE);
906 g_object_class_install_property (obj_class, PROP_PATH, pspec);
907
908 pspec = g_param_spec_boolean ("active", "active", "active", FALSE, G_PARAM_READABLE);
909 g_object_class_install_property (obj_class, PROP_ACTIVE, pspec);
910
911 pspec = g_param_spec_boolean ("urgent", "urgent", "urgent", FALSE, G_PARAM_READABLE);
912 g_object_class_install_property (obj_class, PROP_URGENT, pspec);
913
914 pspec = g_param_spec_boolean ("running", "running", "running", FALSE, G_PARAM_READABLE);
915 g_object_class_install_property (obj_class, PROP_RUNNING, pspec);
916
917 pspec = g_param_spec_boolean ("user-visible", "user-visible", "user-visible", FALSE, G_PARAM_READABLE);
918 g_object_class_install_property (obj_class, PROP_USER_VISIBLE, pspec);
919
920 g_type_class_add_private (obj_class, sizeof (BamfViewPrivate));
921
922 view_signals [ACTIVE_CHANGED] =
923 g_signal_new ("active-changed",
924 G_OBJECT_CLASS_TYPE (klass),
925 G_SIGNAL_RUN_FIRST,
926 G_STRUCT_OFFSET (BamfViewClass, active_changed),
927 NULL, NULL,
928 g_cclosure_marshal_VOID__BOOLEAN,
929 G_TYPE_NONE, 1,
930 G_TYPE_BOOLEAN);
931
932 view_signals [CLOSED] =
933 g_signal_new ("closed",
934 G_OBJECT_CLASS_TYPE (klass),
935 G_SIGNAL_RUN_FIRST,
936 G_STRUCT_OFFSET (BamfViewClass, closed),
937 NULL, NULL,
938 g_cclosure_marshal_VOID__VOID,
939 G_TYPE_NONE, 0);
940
941 view_signals [CHILD_ADDED] =
942 g_signal_new ("child-added",
943 G_OBJECT_CLASS_TYPE (klass),
944 G_SIGNAL_RUN_FIRST,
945 G_STRUCT_OFFSET (BamfViewClass, child_added),
946 NULL, NULL,
947 g_cclosure_marshal_VOID__OBJECT,
948 G_TYPE_NONE, 1,
949 BAMF_TYPE_VIEW);
950
951 view_signals [CHILD_REMOVED] =
952 g_signal_new ("child-removed",
953 G_OBJECT_CLASS_TYPE (klass),
954 G_SIGNAL_RUN_FIRST,
955 G_STRUCT_OFFSET (BamfViewClass, child_removed),
956 NULL, NULL,
957 g_cclosure_marshal_VOID__OBJECT,
958 G_TYPE_NONE, 1,
959 BAMF_TYPE_VIEW);
960
961 view_signals [RUNNING_CHANGED] =
962 g_signal_new ("running-changed",
963 G_OBJECT_CLASS_TYPE (klass),
964 G_SIGNAL_RUN_FIRST,
965 G_STRUCT_OFFSET (BamfViewClass, running_changed),
966 NULL, NULL,
967 g_cclosure_marshal_VOID__BOOLEAN,
968 G_TYPE_NONE, 1,
969 G_TYPE_BOOLEAN);
970
971 view_signals [URGENT_CHANGED] =
972 g_signal_new ("urgent-changed",
973 G_OBJECT_CLASS_TYPE (klass),
974 G_SIGNAL_RUN_FIRST,
975 G_STRUCT_OFFSET (BamfViewClass, urgent_changed),
976 NULL, NULL,
977 g_cclosure_marshal_VOID__BOOLEAN,
978 G_TYPE_NONE, 1,
979 G_TYPE_BOOLEAN);
980
981 view_signals [VISIBLE_CHANGED] =
982 g_signal_new ("user-visible-changed",
983 G_OBJECT_CLASS_TYPE (klass),
984 G_SIGNAL_RUN_FIRST,
985 G_STRUCT_OFFSET (BamfViewClass, user_visible_changed),
986 NULL, NULL,
987 g_cclosure_marshal_VOID__BOOLEAN,
988 G_TYPE_NONE, 1,
989 G_TYPE_BOOLEAN);
990
991 view_signals [NAME_CHANGED] =
992 g_signal_new ("name-changed",
993 G_OBJECT_CLASS_TYPE (klass),
994 0,
995 0, NULL, NULL,
996 bamf_marshal_VOID__STRING_STRING,
997 G_TYPE_NONE, 2,
998 G_TYPE_STRING,
999 G_TYPE_STRING);
1000 }
1001
1002
1003 static void
1004 bamf_view_init (BamfView *self)
1005 {
1006 BamfViewPrivate *priv;
1007 GError *error = NULL;
1008
1009 priv = self->priv = BAMF_VIEW_GET_PRIVATE (self);
1010
1011 priv->is_closed = TRUE;
1012
1013 priv->connection = dbus_g_bus_get (DBUS_BUS_SESSION, &error);
1014 if (priv->connection == NULL)
1015 {
1016 g_critical ("Failed to open connection to bus: %s",
1017 error != NULL ? error->message : "Unknown");
1018 if (error)
1019 g_error_free (error);
1020 return;
1021 }
1022 }