diff options
Diffstat (limited to 'src/indicator-messages.c')
-rw-r--r-- | src/indicator-messages.c | 157 |
1 files changed, 136 insertions, 21 deletions
diff --git a/src/indicator-messages.c b/src/indicator-messages.c index 0f5fa31..1b96464 100644 --- a/src/indicator-messages.c +++ b/src/indicator-messages.c @@ -23,9 +23,16 @@ with this program. If not, see <http://www.gnu.org/licenses/>. #include <string.h> #include <glib.h> #include <glib-object.h> +#include <glib/gi18n.h> #include <gtk/gtk.h> + +#if GTK_CHECK_VERSION(3, 0, 0) +#include <libdbusmenu-gtk3/menu.h> +#include <libdbusmenu-gtk3/menuitem.h> +#else #include <libdbusmenu-gtk/menu.h> #include <libdbusmenu-gtk/menuitem.h> +#endif #include <libindicator/indicator.h> #include <libindicator/indicator-object.h> @@ -52,6 +59,7 @@ typedef struct _IndicatorMessagesClass IndicatorMessagesClass; struct _IndicatorMessagesClass { IndicatorObjectClass parent_class; + void (*update_a11y_desc) (IndicatorServiceManager * service, gpointer * user_data); }; struct _IndicatorMessages { @@ -71,6 +79,8 @@ static GDBusProxy * icon_proxy = NULL; static GtkSizeGroup * indicator_right_group = NULL; static GDBusNodeInfo * bus_node_info = NULL; static GDBusInterfaceInfo * bus_interface_info = NULL; +static const gchar * accessible_desc = NULL; +static IndicatorObject * indicator = NULL; /* Prototypes */ static void indicator_messages_class_init (IndicatorMessagesClass *klass); @@ -79,12 +89,37 @@ static void indicator_messages_dispose (GObject *object); static void indicator_messages_finalize (GObject *object); static GtkImage * get_icon (IndicatorObject * io); static GtkMenu * get_menu (IndicatorObject * io); +static void indicator_messages_middle_click (IndicatorObject * io, + IndicatorObjectEntry * entry, + guint time, gpointer data); +static const gchar * get_accessible_desc (IndicatorObject * io); static void connection_change (IndicatorServiceManager * sm, gboolean connected, gpointer user_data); G_DEFINE_TYPE (IndicatorMessages, indicator_messages, INDICATOR_OBJECT_TYPE); +static void +update_a11y_desc (void) +{ + g_return_if_fail(IS_INDICATOR_MESSAGES(indicator)); + + GList *entries = indicator_object_get_entries(indicator); + IndicatorObjectEntry * entry = (IndicatorObjectEntry *)entries->data; + + entry->accessible_desc = get_accessible_desc(indicator); + + g_signal_emit(G_OBJECT(indicator), + INDICATOR_OBJECT_SIGNAL_ACCESSIBLE_DESC_UPDATE_ID, + 0, + entry, + TRUE); + + g_list_free(entries); + + return; +} + /* Initialize the one-timers */ static void indicator_messages_class_init (IndicatorMessagesClass *klass) @@ -98,6 +133,8 @@ indicator_messages_class_init (IndicatorMessagesClass *klass) io_class->get_image = get_icon; io_class->get_menu = get_menu; + io_class->get_accessible_desc = get_accessible_desc; + io_class->secondary_activate = indicator_messages_middle_click; if (bus_node_info == NULL) { GError * error = NULL; @@ -131,6 +168,8 @@ indicator_messages_init (IndicatorMessages *self) self->service = indicator_service_manager_new_version(INDICATOR_MESSAGES_DBUS_NAME, 1); g_signal_connect(self->service, INDICATOR_SERVICE_MANAGER_SIGNAL_CONNECTION_CHANGE, G_CALLBACK(connection_change), self); + indicator = INDICATOR_OBJECT(self); + return; } @@ -172,8 +211,10 @@ proxy_signal (GDBusProxy * proxy, const gchar * sender, const gchar * signal, GV if (g_strcmp0("AttentionChanged", signal) == 0) { if (prop) { indicator_image_helper_update(GTK_IMAGE(main_image), "indicator-messages-new"); + accessible_desc = _("New Messages"); } else { indicator_image_helper_update(GTK_IMAGE(main_image), "indicator-messages"); + accessible_desc = _("Messages"); } } else if (g_strcmp0("IconChanged", signal) == 0) { if (prop) { @@ -185,6 +226,8 @@ proxy_signal (GDBusProxy * proxy, const gchar * sender, const gchar * signal, GV g_warning("Unknown signal %s", signal); } + update_a11y_desc(); + return; } @@ -205,10 +248,14 @@ attention_cb (GObject * object, GAsyncResult * ares, gpointer user_data) if (prop) { indicator_image_helper_update(GTK_IMAGE(main_image), "indicator-messages-new"); + accessible_desc = _("New Messages"); } else { indicator_image_helper_update(GTK_IMAGE(main_image), "indicator-messages"); + accessible_desc = _("Messages"); } + update_a11y_desc(); + return; } @@ -369,12 +416,18 @@ application_prop_change_cb (DbusmenuMenuitem * mi, gchar * prop, GVariant * valu } /* Draws a triangle on the left, using fg[STATE_TYPE] color. */ +#if GTK_CHECK_VERSION(3, 0, 0) +static gboolean +application_triangle_draw_cb (GtkWidget *widget, cairo_t *cr, gpointer data) +{ +#else static gboolean application_triangle_draw_cb (GtkWidget *widget, GdkEventExpose *event, gpointer data) { + cairo_t *cr; +#endif GtkAllocation allocation; GtkStyle *style; - cairo_t *cr; int x, y, arrow_width, arrow_height; if (!GTK_IS_WIDGET (widget)) return FALSE; @@ -391,13 +444,22 @@ application_triangle_draw_cb (GtkWidget *widget, GdkEventExpose *event, gpointer arrow_width = 5; /* the pixel-based reference triangle is 5x9 */ arrow_height = 9; gtk_widget_get_allocation (widget, &allocation); +#if GTK_CHECK_VERSION(3, 0, 0) + x = 0; + y = allocation.height/2.0 - (double)arrow_height/2.0; +#else x = allocation.x; y = allocation.y + allocation.height/2.0 - (double)arrow_height/2.0; +#endif +#if GTK_CHECK_VERSION(3, 0, 0) + cairo_save (cr); +#else /* initialize cairo drawing area */ cr = (cairo_t*) gdk_cairo_create (gtk_widget_get_window (widget)); +#endif - /* set line width */ + /* set line width */ cairo_set_line_width (cr, 1.0); /* cairo drawing code */ @@ -410,8 +472,12 @@ application_triangle_draw_cb (GtkWidget *widget, GdkEventExpose *event, gpointer style->fg[gtk_widget_get_state(widget)].blue/65535.0); cairo_fill (cr); +#if GTK_CHECK_VERSION(3, 0, 0) + cairo_restore (cr); +#else /* remember to destroy cairo context to avoid leaks */ cairo_destroy (cr); +#endif return FALSE; } @@ -431,12 +497,18 @@ custom_cairo_rounded_rectangle (cairo_t *cr, } /* Draws a rounded rectangle with text inside. */ +#if GTK_CHECK_VERSION(3, 0, 0) +static gboolean +numbers_draw_cb (GtkWidget *widget, cairo_t *cr, gpointer data) +{ +#else static gboolean numbers_draw_cb (GtkWidget *widget, GdkEventExpose *event, gpointer data) { + cairo_t *cr; +#endif GtkAllocation allocation; GtkStyle *style; - cairo_t *cr; double x, y, w, h; PangoLayout * layout; gint font_size = RIGHT_LABEL_FONT_SIZE; @@ -448,10 +520,15 @@ numbers_draw_cb (GtkWidget *widget, GdkEventExpose *event, gpointer data) /* set arrow position / dimensions */ gtk_widget_get_allocation (widget, &allocation); - w = allocation.width; - h = allocation.height; +#if GTK_CHECK_VERSION(3, 0, 0) + x = 0; + y = 0; +#else x = allocation.x; y = allocation.y; +#endif + w = allocation.width; + h = allocation.height; layout = gtk_label_get_layout (GTK_LABEL(widget)); @@ -461,10 +538,14 @@ numbers_draw_cb (GtkWidget *widget, GdkEventExpose *event, gpointer data) /* const PangoFontDescription * font_description = pango_layout_get_font_description (layout); font_size = pango_font_description_get_size (font_description); */ +#if GTK_CHECK_VERSION(3, 0, 0) + cairo_save (cr); +#else /* initialize cairo drawing area */ cr = (cairo_t*) gdk_cairo_create (gtk_widget_get_window (widget)); +#endif - /* set line width */ + /* set line width */ cairo_set_line_width (cr, 1.0); cairo_set_fill_rule (cr, CAIRO_FILL_RULE_EVEN_ODD); @@ -480,8 +561,12 @@ numbers_draw_cb (GtkWidget *widget, GdkEventExpose *event, gpointer data) pango_cairo_layout_path (cr, layout); cairo_fill (cr); +#if GTK_CHECK_VERSION(3, 0, 0) + cairo_restore (cr); +#else /* remember to destroy cairo context to avoid leaks */ - cairo_destroy (cr); + cairo_destroy (cr); +#endif return TRUE; } @@ -489,18 +574,13 @@ numbers_draw_cb (GtkWidget *widget, GdkEventExpose *event, gpointer data) /* Builds a menu item representing a running application in the messaging menu */ static gboolean -new_application_item (DbusmenuMenuitem * newitem, DbusmenuMenuitem * parent, DbusmenuClient * client) +new_application_item (DbusmenuMenuitem * newitem, DbusmenuMenuitem * parent, DbusmenuClient * client, gpointer user_data) { g_debug ("%s (\"%s\")", __func__, dbusmenu_menuitem_property_get(newitem, APPLICATION_MENUITEM_PROP_NAME)); GtkMenuItem * gmi = GTK_MENU_ITEM(gtk_image_menu_item_new()); gtk_image_menu_item_set_always_show_image(GTK_IMAGE_MENU_ITEM(gmi), TRUE); - gint padding = 4; - gtk_widget_style_get(GTK_WIDGET(gmi), "horizontal-padding", &padding, NULL); - - GtkWidget * hbox = gtk_hbox_new(FALSE, 0); - /* Set the minimum size, we always want it to take space */ gint width, height; gtk_icon_size_lookup(GTK_ICON_SIZE_MENU, &width, &height); @@ -517,12 +597,10 @@ new_application_item (DbusmenuMenuitem * newitem, DbusmenuMenuitem * parent, Dbu /* Application name in a label */ GtkWidget * label = gtk_label_new(dbusmenu_menuitem_property_get(newitem, APPLICATION_MENUITEM_PROP_NAME)); gtk_misc_set_alignment(GTK_MISC(label), 0.0, 0.5); - gtk_box_pack_start(GTK_BOX(hbox), label, TRUE, TRUE, padding); gtk_widget_show(label); /* Insert the hbox */ - gtk_container_add(GTK_CONTAINER(gmi), hbox); - gtk_widget_show(hbox); + gtk_container_add(GTK_CONTAINER(gmi), label); /* Attach some of the standard GTK stuff */ dbusmenu_gtkclient_newitem_base(DBUSMENU_GTKCLIENT(client), newitem, gmi, parent); @@ -530,7 +608,11 @@ new_application_item (DbusmenuMenuitem * newitem, DbusmenuMenuitem * parent, Dbu /* Make sure we can handle the label changing */ g_signal_connect(G_OBJECT(newitem), DBUSMENU_MENUITEM_SIGNAL_PROPERTY_CHANGED, G_CALLBACK(application_prop_change_cb), label); g_signal_connect(G_OBJECT(newitem), DBUSMENU_MENUITEM_SIGNAL_PROPERTY_CHANGED, G_CALLBACK(application_icon_change_cb), icon); +#if GTK_CHECK_VERSION(3, 0, 0) + g_signal_connect_after(G_OBJECT (gmi), "draw", G_CALLBACK (application_triangle_draw_cb), newitem); +#else g_signal_connect_after(G_OBJECT (gmi), "expose_event", G_CALLBACK (application_triangle_draw_cb), newitem); +#endif return TRUE; } @@ -595,7 +677,7 @@ indicator_prop_change_cb (DbusmenuMenuitem * mi, gchar * prop, GVariant * value, shifting over and putting the icon in with some right side text that'll be determined by the service. */ static gboolean -new_indicator_item (DbusmenuMenuitem * newitem, DbusmenuMenuitem * parent, DbusmenuClient * client) +new_indicator_item (DbusmenuMenuitem * newitem, DbusmenuMenuitem * parent, DbusmenuClient * client, gpointer user_data) { g_return_val_if_fail(DBUSMENU_IS_MENUITEM(newitem), FALSE); g_return_val_if_fail(DBUSMENU_IS_GTKCLIENT(client), FALSE); @@ -607,9 +689,9 @@ new_indicator_item (DbusmenuMenuitem * newitem, DbusmenuMenuitem * parent, Dbusm gint padding = 4; gint font_size = RIGHT_LABEL_FONT_SIZE; - gtk_widget_style_get(GTK_WIDGET(gmi), "horizontal-padding", &padding, NULL); + gtk_widget_style_get(GTK_WIDGET(gmi), "toggle-spacing", &padding, NULL); - GtkWidget * hbox = gtk_hbox_new(FALSE, 0); + GtkWidget * hbox = gtk_hbox_new(FALSE, padding); /* Icon, probably someone's face or avatar on an IM */ mi_data->icon = gtk_image_new(); @@ -642,7 +724,7 @@ new_indicator_item (DbusmenuMenuitem * newitem, DbusmenuMenuitem * parent, Dbusm g_object_unref(resized_pixbuf); } gtk_misc_set_alignment(GTK_MISC(mi_data->icon), 0.0, 0.5); - gtk_box_pack_start(GTK_BOX(hbox), mi_data->icon, FALSE, FALSE, padding); + gtk_box_pack_start(GTK_BOX(hbox), mi_data->icon, FALSE, FALSE, 0); if (pixbuf != NULL) { gtk_widget_show(mi_data->icon); @@ -651,7 +733,7 @@ new_indicator_item (DbusmenuMenuitem * newitem, DbusmenuMenuitem * parent, Dbusm /* Label, probably a username, chat room or mailbox name */ mi_data->label = gtk_label_new(dbusmenu_menuitem_property_get(newitem, INDICATOR_MENUITEM_PROP_LABEL)); gtk_misc_set_alignment(GTK_MISC(mi_data->label), 0.0, 0.5); - gtk_box_pack_start(GTK_BOX(hbox), mi_data->label, TRUE, TRUE, padding); + gtk_box_pack_start(GTK_BOX(hbox), mi_data->label, TRUE, TRUE, 0); gtk_widget_show(mi_data->label); /* Usually either the time or the count on the individual @@ -659,8 +741,13 @@ new_indicator_item (DbusmenuMenuitem * newitem, DbusmenuMenuitem * parent, Dbusm mi_data->right = gtk_label_new(dbusmenu_menuitem_property_get(newitem, INDICATOR_MENUITEM_PROP_RIGHT)); gtk_size_group_add_widget(indicator_right_group, mi_data->right); /* install extra decoration overlay */ +#if GTK_CHECK_VERSION(3, 0, 0) + g_signal_connect (G_OBJECT (mi_data->right), "draw", + G_CALLBACK (numbers_draw_cb), NULL); +#else g_signal_connect (G_OBJECT (mi_data->right), "expose_event", G_CALLBACK (numbers_draw_cb), NULL); +#endif gtk_misc_set_alignment(GTK_MISC(mi_data->right), 1.0, 0.5); gtk_box_pack_start(GTK_BOX(hbox), mi_data->right, FALSE, FALSE, padding + font_size/2.0); @@ -701,3 +788,31 @@ get_menu (IndicatorObject * io) return GTK_MENU(menu); } + +/* Returns the accessible description of the indicator */ +static const gchar * +get_accessible_desc (IndicatorObject * io) +{ + return accessible_desc; +} + +/* Hide the notifications on middle-click over the indicator-messages */ +static void +indicator_messages_middle_click (IndicatorObject * io, IndicatorObjectEntry * entry, + guint time, gpointer data) +{ + if (icon_proxy == NULL) { + return; + } + + g_dbus_proxy_call(icon_proxy, + "ClearAttention", + NULL, /* params */ + G_DBUS_CALL_FLAGS_NONE, + -1, /* timeout */ + NULL, /* cancel */ + NULL, + NULL); + + return; +} |