Codebase list xapp / 07b1730
Eliminate all appindicator-specific code from xapp-status-icon.c, Add a whitelist for xapp-sn-watcher to list ai icons that should left-click to activate. Michael Webster 4 years ago
5 changed file(s) with 91 addition(s) and 96 deletion(s). Raw diff Collapse all Expand all
308308 return do_activate;
309309 }
310310
311 static gboolean
312 appindicator_can_activate (XAppStatusIcon *icon)
313 {
314 gpointer ptr;
315 gboolean has_activate = FALSE;
316
317 ptr = g_object_get_data (G_OBJECT (icon), "app-indicator-has-secondary-activate");
318
319 if (ptr && GPOINTER_TO_INT (ptr))
320 {
321 has_activate = TRUE;
322 }
323
324 return has_activate;
325 }
326
327 static gboolean
328 handle_appindicator_button_press (XAppStatusIcon *icon,
329 guint button,
330 guint _time)
331 {
332 if (g_object_get_data (G_OBJECT (icon), "app-indicator"))
333 {
334 if (button == GDK_BUTTON_MIDDLE || (button == GDK_BUTTON_PRIMARY && appindicator_can_activate (icon)))
335 {
336 g_debug ("XAppStatusIcon: sending activate for left- or middle-click event (libappindicator)");
337
338 g_signal_emit (icon, signals[ACTIVATE], 0,
339 button,
340 _time);
341 }
342 else
343 {
344 g_debug ("XAppStatusIcon: GtkStatusIcon (app-indicator) ignoring %s button press.", button_to_str (button));
345 }
346
347 return TRUE;
348 }
349
350 return FALSE;
351 }
352
353311 static GtkWidget *
354312 get_menu_to_use (XAppStatusIcon *icon,
355313 guint button)
359317 switch (button)
360318 {
361319 case GDK_BUTTON_PRIMARY:
362 if (g_object_get_data (G_OBJECT (icon), "app-indicator"))
363 {
364 if (!appindicator_can_activate (icon))
365 {
366 menu_to_use = icon->priv->secondary_menu;
367 break;
368 }
369 }
370
371320 menu_to_use = icon->priv->primary_menu;
372321 break;
373322 case GDK_BUTTON_SECONDARY:
397346 g_dbus_method_invocation_get_sender (invocation),
398347 x, y, button_to_str (button), _time, panel_position_to_str (panel_position));
399348
400 if (!handle_appindicator_button_press (icon, button, _time))
349 if (should_send_activate (icon, button))
401350 {
402 if (should_send_activate (icon, button))
403 {
404 g_debug ("XAppStatusIcon: native sending 'activate' for %s button", button_to_str (button));
405 g_signal_emit (icon, signals[ACTIVATE], 0,
406 button,
407 _time);
408 }
351 g_debug ("XAppStatusIcon: native sending 'activate' for %s button", button_to_str (button));
352 g_signal_emit (icon, signals[ACTIVATE], 0,
353 button,
354 _time);
409355 }
410356
411357 icon->priv->have_button_press = TRUE;
578524 button = event->button.button;
579525 _time = event->button.time;
580526
581 /* Button press equates to activate when there's no menu,
582 * but for appindicator, left click and right click will always
583 * bring up the same menu, and only a middle click should activate. */
584
585527 g_debug ("XAppStatusIcon: GtkStatusIcon button-press-event with %s button", button_to_str (button));
586528
587 if (!handle_appindicator_button_press (icon, button, _time))
588 {
589529 /* We always send 'activate' for a button that has no corresponding menu,
590530 * and for middle clicks. */
591 if (should_send_activate (icon, button))
592 {
593 g_debug ("XAppStatusIcon: GtkStatusIcon activated by %s button", button_to_str (button));
594
595 g_signal_emit (icon, signals[ACTIVATE], 0,
596 button,
597 _time);
598 }
531 if (should_send_activate (icon, button))
532 {
533 g_debug ("XAppStatusIcon: GtkStatusIcon activated by %s button", button_to_str (button));
534
535 g_signal_emit (icon, signals[ACTIVATE], 0,
536 button,
537 _time);
599538 }
600539
601540 calculate_gtk_status_icon_position_and_orientation (icon,
16181557 GtkMenu *menu)
16191558 {
16201559 g_return_if_fail (XAPP_IS_STATUS_ICON (icon));
1621 g_return_if_fail (GTK_IS_MENU (menu));
1560 g_return_if_fail (GTK_IS_MENU (menu) || menu == NULL);
16221561
16231562 if (menu == GTK_MENU (icon->priv->primary_menu))
16241563 {
16701609 GtkMenu *menu)
16711610 {
16721611 g_return_if_fail (XAPP_IS_STATUS_ICON (icon));
1673 g_return_if_fail (GTK_IS_MENU (menu));
1612 g_return_if_fail (GTK_IS_MENU (menu) || menu == NULL);
16741613
16751614 if (menu == GTK_MENU (icon->priv->secondary_menu))
16761615 {
00 <?xml version="1.0"?>
11 <schemalist>
22 <schema id="org.x.apps" path="/org/x/apps/">
3
3 <key name="left-click-activate-apps" type="as">
4 <default>["Onboard"]</default>
5 <summary>A list of appindicator-based apps where left-click should trigger the 'secondary activation' action, rather than open the menu.</summary>
6 <description>The name to be put here will be the icon's "Name" (not icon name). You can see what name to use by running xapp-sn-watcher from a terminal (or in .xsession-properties in some DEs).
7 </description>
8 </key>
49 </schema>
510 </schemalist>
4040 gchar *png_path;
4141
4242 gint current_icon_id;
43 gchar *sortable_name;
4344
4445 gboolean is_ai;
4546 };
5152 static void update_tooltip (SnItem *item);
5253 static void update_icon (SnItem *item);
5354
55 static gboolean
56 should_activate (SnItem *item)
57 {
58 gboolean should;
59
60 gchar **whitelist = g_settings_get_strv (xapp_settings,
61 WHITELIST_KEY);
62
63 should = g_strv_contains ((const gchar * const *) whitelist, item->sortable_name);
64 g_strfreev (whitelist);
65
66 return should;
67 }
68
5469 static void
5570 sn_item_init (SnItem *self)
5671 {
7691 item->last_png_path = NULL;
7792 }
7893
94 g_clear_pointer (&item->sortable_name, g_free);
7995 g_clear_object (&item->status_icon);
8096 g_clear_object (&item->menu);
8197 g_clear_object (&item->prop_proxy);
518534 {
519535 gchar *menu_path;
520536
537 g_clear_object (&item->menu);
538
539 xapp_status_icon_set_primary_menu (item->status_icon, NULL);
540 xapp_status_icon_set_secondary_menu (item->status_icon, NULL);
541
521542 menu_path = get_string_property (item, "Menu");
522543
523544 if (menu_path == NULL)
524545 {
525 g_clear_object (&item->menu);
526
527 xapp_status_icon_set_secondary_menu (item->status_icon, NULL);
528546 return;
529547 }
530548
531549 item->menu = GTK_WIDGET (dbusmenu_gtkmenu_new ((gchar *) g_dbus_proxy_get_name (item->sn_item_proxy), menu_path));
532550 g_object_ref_sink (item->menu);
551
552 if (item->is_ai && !should_activate (item))
553 {
554 xapp_status_icon_set_primary_menu (item->status_icon, GTK_MENU (item->menu));
555 }
533556
534557 xapp_status_icon_set_secondary_menu (item->status_icon, GTK_MENU (item->menu));
535558
728751 {
729752 SnItem *item = SN_ITEM (user_data);
730753
731 GError *error = NULL;
732
733754 if (button == GDK_BUTTON_PRIMARY)
734755 {
735 /* This sucks, nothing is consistent. Most programs don't have a primary
736 activate (all appindicator ones). One that I checked that does, claims
737 (according to proxyinfo.get_method_info()) it only accepts SecondaryActivate,
738 but only listens for "Activate", so we attempt a sync primary call, and async
739 secondary if needed. Otherwise we're waiting for the first to finish in a
740 callback before we can try the secondary. Maybe we just call secondary always?? */
741
742 sn_item_interface_call_activate_sync (SN_ITEM_INTERFACE (item->sn_item_proxy), x, y, NULL, &error);
743
744 if (error != NULL)
745 {
746 g_error_free (error);
747
748 sn_item_interface_call_secondary_activate (SN_ITEM_INTERFACE (item->sn_item_proxy), x, y, NULL, NULL, NULL);
756 if (item->is_ai)
757 {
758 if (should_activate (item))
759 {
760 sn_item_interface_call_secondary_activate (SN_ITEM_INTERFACE (item->sn_item_proxy), x, y, NULL, NULL, NULL);
761 return;
762 }
763 } else
764 {
765 sn_item_interface_call_activate (SN_ITEM_INTERFACE (item->sn_item_proxy), x, y, NULL, NULL, NULL);
749766 }
750767 }
751768 else
828845 g_debug ("Sort name for %s is '%s'", g_dbus_proxy_get_name (G_DBUS_PROXY (item->sn_item_proxy)), sortable_name);
829846 xapp_status_icon_set_name (status_icon, sortable_name);
830847
831 g_free (sortable_name);
848 item->sortable_name = sortable_name;
832849 }
833850
834851 static void
894911
895912 initialize_item (item);
896913 return item;
914 }
915
916 void
917 sn_item_update_menus (SnItem *item)
918 {
919 update_menu (item);
897920 }
1212 G_DECLARE_FINAL_TYPE (SnItem, sn_item, SN, ITEM, GObject)
1313
1414 SnItem *sn_item_new (GDBusProxy *sn_item_proxy, gboolean is_ai);
15 void sn_item_update_menus (SnItem *item);
16
17 #define WHITELIST_KEY "left-click-activate-apps"
18 extern GSettings *xapp_settings;
1519
1620 G_END_DECLS
1721
3636
3737 #define STATUS_ICON_MONITOR_MATCH "org.x.StatusIconMonitor"
3838 #define APPINDICATOR_PATH_PREFIX "/org/ayatana/NotificationItem/"
39
40 GSettings *xapp_settings;
3941
4042 static void continue_startup (XAppSnWatcher *watcher);
4143 static void update_published_items (XAppSnWatcher *watcher);
405407 }
406408
407409 static void
410 update_item_menus (const gchar *key,
411 gpointer item,
412 gpointer user_data)
413 {
414 sn_item_update_menus (SN_ITEM (item));
415 }
416
417 static void
418 whitelist_changed (XAppSnWatcher *watcher)
419 {
420 g_hash_table_foreach (watcher->items, (GHFunc) update_item_menus, NULL);
421 }
422
423 static void
408424 continue_startup (XAppSnWatcher *watcher)
409425 {
410426 g_debug ("Trying to acquire session bus connection");
431447
432448 G_APPLICATION_CLASS (xapp_sn_watcher_parent_class)->startup (application);
433449
450 xapp_settings = g_settings_new ("org.x.apps");
451 g_signal_connect_swapped (xapp_settings,
452 "changed::" WHITELIST_KEY,
453 G_CALLBACK (whitelist_changed),
454 watcher);
455
434456 watcher->items = g_hash_table_new_full (g_str_hash, g_str_equal,
435457 g_free, g_object_unref);
436458
474496 watcher_shutdown (GApplication *application)
475497 {
476498 XAppSnWatcher *watcher = (XAppSnWatcher *) application;
499
500 g_clear_object (&xapp_settings);
477501
478502 if (watcher->name_listener_id > 0)
479503 {