~indicator-applet-developers/indicator-appmenu/trunk.12.10

« back to all changes in this revision

Viewing changes to src/hudmenumodelcollector.c

  • Committer: Lars Uebernickel
  • Date: 2012-10-04 14:56:48 UTC
  • mfrom: (212.1.1 indicator-appmenu)
  • Revision ID: lars.uebernickel@canonical.com-20121004145648-c0b4uc0mo1kfier2
Merge lp:~desrt/indicator-appmenu/hud-awareness

Implement the GMenuModel hud-awareness protocol.

Show diffs side-by-side

added added

removed removed

Lines of Context:
60
60
{
61
61
  GObject parent_instance;
62
62
 
63
 
  GSList *models;
64
 
  guint refresh_id;
65
 
  /* stuff... */
66
 
  GDBusMenuModel *app_menu;
67
 
  GDBusMenuModel *menubar;
 
63
  /* Cancelled on finalize */
 
64
  GCancellable *cancellable;
 
65
 
 
66
  /* GDBus shared session bus and D-Bus name of the app/indicator */
 
67
  GDBusConnection *session;
 
68
  gchar *unique_bus_name;
 
69
 
 
70
  /* If this is an application, is_application will be set and
 
71
   * 'application' and 'window' will contain the two action groups for
 
72
   * the window that we are collecting.
 
73
   *
 
74
   * If this is an indicator, is_application will be false and the
 
75
   * (singular) action group for the indicator will be in 'application'.
 
76
   */
68
77
  GDBusActionGroup *application;
69
78
  GDBusActionGroup *window;
70
 
 
71
79
  gboolean is_application;
72
80
 
 
81
  /* The GMenuModel for the app menu.
 
82
   *
 
83
   * If this is an indicator, the indicator menu is stored here.
 
84
   *
 
85
   * app_menu_is_hud_aware is TRUE if we should send HudActiveChanged
 
86
   * calls to app_menu_object_path when our use_count goes above 0.
 
87
   */
 
88
  GDBusMenuModel *app_menu;
 
89
  gchar *app_menu_object_path;
 
90
  gboolean app_menu_is_hud_aware;
 
91
 
 
92
  /* Ditto for the menubar.
 
93
   *
 
94
   * If this is an indicator then these will all be unset.
 
95
   */
 
96
  GDBusMenuModel *menubar;
 
97
  gchar *menubar_object_path;
 
98
  gboolean menubar_is_hud_aware;
 
99
 
 
100
  /* Boring details about the app/indicator we are showing. */
73
101
  gchar *prefix;
74
102
  gchar *desktop_file;
75
103
  gchar *icon;
 
104
  guint penalty;
 
105
 
 
106
  /* Each time we see a new menumodel added we add it to 'models', start
 
107
   * watching it for changes and add its contents to 'items', possibly
 
108
   * finding more menumodels to do the same to.
 
109
   *
 
110
   * Each time an item is removed, we schedule an idle (in 'refresh_id')
 
111
   * to wipe out all the 'items', disconnect signals from each model in
 
112
   * 'models' and add them all back again.
 
113
   *
 
114
   * Searching just iterates over 'items'.
 
115
   */
76
116
  GPtrArray *items;
 
117
  GSList *models;
 
118
  guint refresh_id;
 
119
 
 
120
  /* Keep track of our use_count in order to send signals to HUD-aware
 
121
   * apps and indicators.
 
122
   */
77
123
  gint use_count;
78
 
  guint penalty;
79
124
};
80
125
 
81
126
typedef struct
151
196
  return context;
152
197
}
153
198
 
154
 
 
155
 
 
156
 
 
157
199
G_DEFINE_TYPE (HudModelItem, hud_model_item, HUD_TYPE_ITEM)
158
200
 
159
201
static void
432
474
}
433
475
 
434
476
static void
 
477
hud_menu_model_collector_active_changed (HudMenuModelCollector *collector,
 
478
                                         gboolean               active)
 
479
{
 
480
  if (collector->app_menu_is_hud_aware)
 
481
    g_dbus_connection_call (collector->session, collector->unique_bus_name, collector->app_menu_object_path,
 
482
                            "com.canonical.hud.Awareness", "HudActiveChanged", g_variant_new ("(b)", active),
 
483
                            NULL, G_DBUS_CALL_FLAGS_NONE, -1, NULL, NULL, NULL);
 
484
 
 
485
  if (collector->menubar_is_hud_aware)
 
486
    g_dbus_connection_call (collector->session, collector->unique_bus_name, collector->app_menu_object_path,
 
487
                            "com.canonical.hud.Awareness", "HudActiveChanged", g_variant_new ("(b)", active),
 
488
                            NULL, G_DBUS_CALL_FLAGS_NONE, -1, NULL, NULL, NULL);
 
489
}
 
490
 
 
491
static void
435
492
hud_menu_model_collector_use (HudSource *source)
436
493
{
437
494
  HudMenuModelCollector *collector = HUD_MENU_MODEL_COLLECTOR (source);
438
495
 
 
496
  if (collector->use_count == 0)
 
497
    hud_menu_model_collector_active_changed (collector, TRUE);
 
498
 
439
499
  collector->use_count++;
440
500
}
441
501
 
445
505
  HudMenuModelCollector *collector = HUD_MENU_MODEL_COLLECTOR (source);
446
506
 
447
507
  collector->use_count--;
 
508
 
 
509
  if (collector->use_count == 0)
 
510
    hud_menu_model_collector_active_changed (collector, FALSE);
448
511
}
449
512
 
450
513
static void
474
537
{
475
538
  HudMenuModelCollector *collector = HUD_MENU_MODEL_COLLECTOR (object);
476
539
 
 
540
  g_cancellable_cancel (collector->cancellable);
 
541
  g_object_unref (collector->cancellable);
 
542
 
477
543
  if (collector->refresh_id)
478
544
    g_source_remove (collector->refresh_id);
479
545
 
483
549
  g_clear_object (&collector->application);
484
550
  g_clear_object (&collector->window);
485
551
 
 
552
  g_object_unref (collector->session);
 
553
  g_free (collector->unique_bus_name);
 
554
  g_free (collector->app_menu_object_path);
 
555
  g_free (collector->menubar_object_path);
486
556
  g_free (collector->prefix);
487
557
  g_free (collector->desktop_file);
488
558
  g_free (collector->icon);
497
567
hud_menu_model_collector_init (HudMenuModelCollector *collector)
498
568
{
499
569
  collector->items = g_ptr_array_new_with_free_func (g_object_unref);
 
570
  collector->cancellable = g_cancellable_new ();
500
571
}
501
572
 
502
573
static void
513
584
  class->finalize = hud_menu_model_collector_finalize;
514
585
}
515
586
 
 
587
static void
 
588
hud_menu_model_collector_hud_awareness_cb (GObject      *source,
 
589
                                           GAsyncResult *result,
 
590
                                           gpointer      user_data)
 
591
{
 
592
  GVariant *reply;
 
593
 
 
594
  /* The goal of this function is to set either the
 
595
   * app_menu_is_hud_aware or menubar_is_hud_aware flag (which we have a
 
596
   * pointer to in user_data) to TRUE in the case that the remote
 
597
   * appears to support the com.canonical.hud.Awareness protocol.
 
598
   *
 
599
   * If it supports it, the async call will be successful.  In that
 
600
   * case, we want to set *(gboolean *) user_data = TRUE;
 
601
   *
 
602
   * There are two cases that we don't want to do that write.  The first
 
603
   * is the event that the remote doesn't support the protocol.  In that
 
604
   * case, we will see an error when we inspect the result.  The other
 
605
   * is the case in which the flag to which user_data points no longer
 
606
   * exists (ie: collector has been finalized).  In this case, the
 
607
   * cancellable will have been cancelled and we will also see an error.
 
608
   *
 
609
   * Long story short: If we get any error, just do nothing.
 
610
   */
 
611
 
 
612
  reply = g_dbus_connection_call_finish (G_DBUS_CONNECTION (source), result, NULL);
 
613
 
 
614
  if (reply)
 
615
    {
 
616
      *(gboolean *) user_data = TRUE;
 
617
      g_variant_unref (reply);
 
618
    }
 
619
}
 
620
 
516
621
/**
517
622
 * hud_menu_model_collector_get:
518
623
 * @window: a #BamfWindow
533
638
{
534
639
  HudMenuModelCollector *collector;
535
640
  gchar *unique_bus_name;
536
 
  gchar *app_menu_object_path;
537
 
  gchar *menubar_object_path;
538
641
  gchar *application_object_path;
539
642
  gchar *window_object_path;
540
643
  GDBusConnection *session;
541
644
 
 
645
  session = g_bus_get_sync (G_BUS_TYPE_SESSION, NULL, NULL);
 
646
 
 
647
  if (!session)
 
648
    return NULL;
 
649
 
542
650
  unique_bus_name = bamf_window_get_utf8_prop (window, "_GTK_UNIQUE_BUS_NAME");
543
651
 
544
652
  if (!unique_bus_name)
546
654
    return NULL;
547
655
 
548
656
  collector = g_object_new (HUD_TYPE_MENU_MODEL_COLLECTOR, NULL);
 
657
  collector->session = session;
 
658
  collector->unique_bus_name = unique_bus_name;
549
659
 
550
 
  app_menu_object_path = bamf_window_get_utf8_prop (window, "_GTK_APP_MENU_OBJECT_PATH");
551
 
  menubar_object_path = bamf_window_get_utf8_prop (window, "_GTK_MENUBAR_OBJECT_PATH");
 
660
  collector->app_menu_object_path = bamf_window_get_utf8_prop (window, "_GTK_APP_MENU_OBJECT_PATH");
 
661
  collector->menubar_object_path = bamf_window_get_utf8_prop (window, "_GTK_MENUBAR_OBJECT_PATH");
552
662
  application_object_path = bamf_window_get_utf8_prop (window, "_GTK_APPLICATION_OBJECT_PATH");
553
663
  window_object_path = bamf_window_get_utf8_prop (window, "_GTK_WINDOW_OBJECT_PATH");
554
664
 
555
 
  session = g_bus_get_sync (G_BUS_TYPE_SESSION, NULL, NULL);
556
 
 
557
 
  if (app_menu_object_path)
 
665
  if (collector->app_menu_object_path)
558
666
    {
559
 
      collector->app_menu = g_dbus_menu_model_get (session, unique_bus_name, app_menu_object_path);
 
667
      collector->app_menu = g_dbus_menu_model_get (session, unique_bus_name, collector->app_menu_object_path);
560
668
      hud_menu_model_collector_add_model (collector, G_MENU_MODEL (collector->app_menu), NULL, NULL, NULL);
 
669
      g_dbus_connection_call (session, unique_bus_name, collector->app_menu_object_path,
 
670
                              "com.canonical.hud.Awareness", "CheckAwareness",
 
671
                              NULL, G_VARIANT_TYPE_UNIT, G_DBUS_CALL_FLAGS_NONE, -1, collector->cancellable,
 
672
                              hud_menu_model_collector_hud_awareness_cb, &collector->app_menu_is_hud_aware);
561
673
    }
562
674
 
563
 
  if (menubar_object_path)
 
675
  if (collector->menubar_object_path)
564
676
    {
565
 
      collector->menubar = g_dbus_menu_model_get (session, unique_bus_name, menubar_object_path);
 
677
      collector->menubar = g_dbus_menu_model_get (session, unique_bus_name, collector->menubar_object_path);
566
678
      hud_menu_model_collector_add_model (collector, G_MENU_MODEL (collector->menubar), NULL, NULL, NULL);
 
679
      g_dbus_connection_call (session, unique_bus_name, collector->app_menu_object_path,
 
680
                              "com.canonical.hud.Awareness", "CheckAwareness",
 
681
                              NULL, G_VARIANT_TYPE_UNIT, G_DBUS_CALL_FLAGS_NONE, -1, collector->cancellable,
 
682
                              hud_menu_model_collector_hud_awareness_cb, &collector->menubar_is_hud_aware);
567
683
    }
568
684
 
569
685
  if (application_object_path)
580
696
   * enabled/disabled.  how to deal with that?
581
697
   */
582
698
 
583
 
  g_free (unique_bus_name);
584
 
  g_free (app_menu_object_path);
585
 
  g_free (menubar_object_path);
586
699
  g_free (application_object_path);
587
700
  g_free (window_object_path);
588
701
 
589
 
  g_object_unref (session);
590
 
 
591
702
  return collector;
592
703
}
593
704