aboutsummaryrefslogtreecommitdiff
path: root/src/indicator-messages.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/indicator-messages.c')
-rw-r--r--src/indicator-messages.c157
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;
+}