diff options
-rw-r--r-- | src/Makefile.am | 2 | ||||
-rw-r--r-- | src/indicator-session.c | 38 | ||||
-rw-r--r-- | src/session-service.c | 5 | ||||
-rw-r--r-- | src/user-widget.c | 303 | ||||
-rw-r--r-- | src/user-widget.h | 54 |
5 files changed, 389 insertions, 13 deletions
diff --git a/src/Makefile.am b/src/Makefile.am index df0ec0f..71537c5 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -14,6 +14,8 @@ libsession_la_SOURCES = \ gen-session-dbus.xml.h \ dbus-shared-names.h \ dbusmenu-shared.h \ + user-widget.c \ + user-widget.h \ accounts-service-client.h \ accounts-service-user-client.h libsession_la_CFLAGS = \ diff --git a/src/indicator-session.c b/src/indicator-session.c index 23d7f37..35a55e0 100644 --- a/src/indicator-session.c +++ b/src/indicator-session.c @@ -44,6 +44,7 @@ with this program. If not, see <http://www.gnu.org/licenses/>. #include "dbus-shared-names.h" #include "dbusmenu-shared.h" +#include "user-widget.h" #define INDICATOR_SESSION_TYPE (indicator_session_get_type ()) #define INDICATOR_SESSION(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), INDICATOR_SESSION_TYPE, IndicatorSession)) @@ -83,10 +84,6 @@ static gboolean new_user_item (DbusmenuMenuitem * newitem, DbusmenuMenuitem * parent, DbusmenuClient * client, gpointer user_data); -static void user_property_change (DbusmenuMenuitem * item, - const gchar * property, - GVariant * variant, - gpointer user_data); static gboolean build_restart_item (DbusmenuMenuitem * newitem, DbusmenuMenuitem * parent, DbusmenuClient * client, @@ -282,7 +279,25 @@ new_user_item (DbusmenuMenuitem * newitem, DbusmenuClient * client, gpointer user_data) { - g_debug ("new user item called "); + + + GtkWidget* user_item = NULL; + + g_return_val_if_fail(DBUSMENU_IS_MENUITEM(newitem), FALSE); + g_return_val_if_fail(DBUSMENU_IS_GTKCLIENT(client), FALSE); + + user_item = user_widget_new(newitem); + + GtkMenuItem *user_widget = GTK_MENU_ITEM(user_item); + + gtk_widget_show_all (user_item); + dbusmenu_gtkclient_newitem_base (DBUSMENU_GTKCLIENT(client), + newitem, + user_widget, + parent); + return TRUE; + + /*g_debug ("new user item called "); GtkMenuItem * gmi = GTK_MENU_ITEM(gtk_menu_item_new()); gint padding = 0; gtk_widget_style_get(GTK_WIDGET(gmi), "horizontal-padding", &padding, NULL); @@ -320,12 +335,14 @@ new_user_item (DbusmenuMenuitem * newitem, gtk_widget_show(usericon); } - GtkWidget * label = gtk_label_new(dbusmenu_menuitem_property_get(newitem, USER_ITEM_PROP_NAME)); + GtkWidget * label = gtk_label_new(dbusmenu_menuitem_property_get (newitem, + USER_ITEM_PROP_NAME)); gtk_misc_set_alignment(GTK_MISC(label), 0.0, 0.5); gtk_box_pack_start(GTK_BOX(hbox), label, TRUE, TRUE, 0); gtk_widget_show(label); - GtkWidget * icon = gtk_image_new_from_icon_name("account-logged-in", GTK_ICON_SIZE_MENU); + GtkWidget * icon = gtk_image_new_from_icon_name ("account-logged-in", + GTK_ICON_SIZE_MENU); gtk_misc_set_alignment(GTK_MISC(icon), 1.0, 0.5); gtk_box_pack_start(GTK_BOX(hbox), icon, FALSE, FALSE, 0); if (dbusmenu_menuitem_property_get_bool(newitem, USER_ITEM_PROP_LOGGED_IN)) { @@ -344,9 +361,10 @@ new_user_item (DbusmenuMenuitem * newitem, G_CALLBACK(user_property_change), icon); return TRUE; + */ } -static void +/*static void user_property_change (DbusmenuMenuitem * item, const gchar * property, GVariant * variant, @@ -360,7 +378,7 @@ user_property_change (DbusmenuMenuitem * item, } } return; -} +}*/ static void icon_name_get_cb (GObject * obj, GAsyncResult * res, gpointer user_data) @@ -382,7 +400,7 @@ icon_name_get_cb (GObject * obj, GAsyncResult * res, gpointer user_data) return; } - indicator_image_helper_update(self->users.image, name); + //indicator_image_helper_update(self->users.image, name); return; } diff --git a/src/session-service.c b/src/session-service.c index 001d0e6..fb5c7a9 100644 --- a/src/session-service.c +++ b/src/session-service.c @@ -759,7 +759,6 @@ restart_dir_changed (void) session_dbus_set_name(session_dbus, ICON_DEFAULT); } } - return; } @@ -794,8 +793,8 @@ main (int argc, char ** argv) IndicatorService * service = indicator_service_new_version(INDICATOR_SESSION_DBUS_NAME, INDICATOR_SESSION_DBUS_VERSION); g_signal_connect(G_OBJECT(service), - INDICATOR_SERVICE_SIGNAL_SHUTDOWN, - G_CALLBACK(service_shutdown), NULL); + INDICATOR_SERVICE_SIGNAL_SHUTDOWN, + G_CALLBACK(service_shutdown), NULL); session_dbus = session_dbus_new(); diff --git a/src/user-widget.c b/src/user-widget.c new file mode 100644 index 0000000..bd6634a --- /dev/null +++ b/src/user-widget.c @@ -0,0 +1,303 @@ +/* +Copyright 2011 Canonical Ltd. + +Authors: + Conor Curran <conor.curran@canonical.com> + +This program is free software: you can redistribute it and/or modify it +under the terms of the GNU General Public License version 3, as published +by the Free Software Foundation. + +This program is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranties of +MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR +PURPOSE. See the GNU General Public License for more details. + +You should have received a copy of the GNU General Public License along +with this program. If not, see <http://www.gnu.org/licenses/>. +*/ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include <glib/gi18n.h> +#include <gtk/gtk.h> +#include <glib.h> +#include <libindicator/indicator-image-helper.h> +#include "user-widget.h" + +typedef struct _UserWidgetPrivate UserWidgetPrivate; + +struct _UserWidgetPrivate +{ + DbusmenuMenuitem* twin_item; + GtkWidget* user_image; + GtkWidget* user_name; + gboolean logged_in; + gboolean sessions_active; +}; + +#define USER_WIDGET_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), USER_WIDGET_TYPE, UserWidgetPrivate)) + +/* Prototypes */ +static void user_widget_class_init (UserWidgetClass *klass); +static void user_widget_init (UserWidget *self); +static void user_widget_dispose (GObject *object); +static void user_widget_finalize (GObject *object); + +static void user_widget_set_twin_item (UserWidget* self, + DbusmenuMenuitem* twin_item); +// keyevent consumers +static gboolean user_widget_button_release_event (GtkWidget *menuitem, + GdkEventButton *event); +// Dbusmenuitem properties update callback +static void user_widget_property_update (DbusmenuMenuitem* item, + gchar* property, + GVariant* value, + gpointer userdata); +#if GTK_CHECK_VERSION(3, 0, 0) +static gboolean user_widget_primitive_draw_cb_gtk_3 (GtkWidget *image, + cairo_t* cr, + gpointer user_data); +#else +static gboolean user_widget_primitive_draw_cb (GtkWidget *image, + GdkEventExpose *event, + gpointer user_data); +#endif + +G_DEFINE_TYPE (UserWidget, user_widget, GTK_TYPE_MENU_ITEM); + +static void +user_widget_class_init (UserWidgetClass *klass) +{ + GObjectClass *gobject_class = G_OBJECT_CLASS (klass); + GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass); + + widget_class->button_release_event = user_widget_button_release_event; + + g_type_class_add_private (klass, sizeof (UserWidgetPrivate)); + + gobject_class->dispose = user_widget_dispose; + gobject_class->finalize = user_widget_finalize; +} + +static void +user_widget_init (UserWidget *self) +{ + UserWidgetPrivate * priv = USER_WIDGET_GET_PRIVATE(self); + priv->user_image = NULL; + priv->user_name = NULL; + priv->logged_in = FALSE; + priv->sessions_active = FALSE; + + priv->user_image = gtk_image_new (); + + // Just for now set the image to the default avator image + GdkPixbuf* pixbuf = NULL; + GError* error = NULL; + pixbuf = gtk_icon_theme_load_icon (gtk_icon_theme_get_default (), + "avatar-default", + 12, + GTK_ICON_LOOKUP_FORCE_SIZE, + &error); + + if (pixbuf == NULL || error != NULL) { + g_warning ("Could not load the default avatar image for some reason"); + } + else{ + gtk_image_set_from_pixbuf (GTK_IMAGE(priv->user_image), pixbuf); + g_object_unref (pixbuf); + } + + priv->user_name = gtk_label_new (""); + + #if GTK_CHECK_VERSION(3, 0, 0) + g_signal_connect_after (GTK_WIDGET(self), "draw", + G_CALLBACK(user_widget_primitive_draw_cb_gtk_3), + GTK_WIDGET(self)); + #else + g_signal_connect_after (GTK_WIDGET(self), "expose-event", + G_CALLBACK(user_widget_primitive_draw_cb), + GTK_WIDGET(self)); + #endif +} + +static void +user_widget_dispose (GObject *object) +{ + //UserWidgetPrivate * priv = USER_WIDGET_GET_PRIVATE(USER_WIDGET(object)); + + G_OBJECT_CLASS (user_widget_parent_class)->dispose (object); +} + +// TODO tidy up image and name +static void +user_widget_finalize (GObject *object) +{ + G_OBJECT_CLASS (user_widget_parent_class)->finalize (object); +} + +/** + * We override the expose method to enable primitive drawing of the + * empty album art image and rounded rectangles on the album art. + */ + +#if GTK_CHECK_VERSION(3, 0, 0) + +// Draw the triangle if the player is running ... +static gboolean +user_widget_primitive_draw_cb_gtk_3 (GtkWidget *widget, + cairo_t* cr, + gpointer user_data) +{ + /* + g_return_val_if_fail(IS_USER_WIDGET(user_data), FALSE); + UserWidget* meta = USER_WIDGET(user_data); + UserWidgetPrivate * priv = USER_WIDGET_GET_PRIVATE(meta); + + GtkStyle *style; + int x, y, arrow_width, arrow_height; + + gint offset = 3; + arrow_width = 5; + arrow_height = 9; + + style = gtk_widget_get_style (widget); + + GtkAllocation allocation; + gtk_widget_get_allocation (widget, &allocation); + x = allocation.x; + y = 0; + + // Draw player icon + if (priv->icon_buf != NULL){ + gdk_cairo_set_source_pixbuf (cr, + priv->icon_buf, + x + arrow_width + 1, + y + offset); + cairo_paint (cr); + } + + // Draw triangle but only if the player is running. + if (dbusmenu_menuitem_property_get_bool (priv->twin_item, + DBUSMENU_METADATA_MENUITEM_PLAYER_RUNNING)){ + y += (double)arrow_height/2.0 + offset; + cairo_set_line_width (cr, 1.0); + + //g_debug ("triangle drawing"); + + cairo_move_to (cr, x, y); + cairo_line_to (cr, x, y + arrow_height); + cairo_line_to (cr, x + arrow_width, y + (double)arrow_height/2.0); + cairo_close_path (cr); + cairo_set_source_rgb (cr, style->fg[gtk_widget_get_state(widget)].red/65535.0, + style->fg[gtk_widget_get_state(widget)].green/65535.0, + style->fg[gtk_widget_get_state(widget)].blue/65535.0); + cairo_fill (cr); + }*/ + + return FALSE; +} + +// GTK 2 Expose handler +#else + +// Draw the triangle if the player is running ... +static gboolean +user_widget_primitive_draw_cb (GtkWidget *widget, + GdkEventExpose *event, + gpointer user_data) +{ + /* + g_return_val_if_fail(IS_USER_WIDGET(user_data), FALSE); + UserWidget* meta = USER_WIDGET(user_data); + UserWidgetPrivate * priv = USER_WIDGET_GET_PRIVATE(meta); + + GtkStyle *style; + cairo_t *cr; + int x, y, arrow_width, arrow_height; + + gint offset = 3; + arrow_width = 5; + arrow_height = 9; + + style = gtk_widget_get_style (widget); + + cr = (cairo_t*) gdk_cairo_create (gtk_widget_get_window (widget)); + + GtkAllocation allocation; + gtk_widget_get_allocation (widget, &allocation); + x = allocation.x; + y = allocation.y; + + // Draw player icon + if (priv->icon_buf != NULL){ + gdk_cairo_set_source_pixbuf (cr, + priv->icon_buf, + x + arrow_width + 1, + y + offset); + cairo_paint (cr); + } + + // Draw triangle but only if the player is running. + if (dbusmenu_menuitem_property_get_bool (priv->twin_item, + DBUSMENU_METADATA_MENUITEM_PLAYER_RUNNING)){ + y += (double)arrow_height/2.0 + offset; + cairo_set_line_width (cr, 1.0); + + cairo_move_to (cr, x, y); + cairo_line_to (cr, x, y + arrow_height); + cairo_line_to (cr, x + arrow_width, y + (double)arrow_height/2.0); + cairo_close_path (cr); + cairo_set_source_rgb (cr, style->fg[gtk_widget_get_state(widget)].red/65535.0, + style->fg[gtk_widget_get_state(widget)].green/65535.0, + style->fg[gtk_widget_get_state(widget)].blue/65535.0); + cairo_fill (cr); + } + + cairo_destroy (cr);*/ + return FALSE; +} +#endif + + +/* Suppress/consume keyevents */ +static gboolean +user_widget_button_release_event (GtkWidget *menuitem, + GdkEventButton *event) +{ + return FALSE; +} + +static void +user_widget_property_update (DbusmenuMenuitem* item, gchar* property, + GVariant* value, gpointer userdata) +{ + g_return_if_fail (IS_USER_WIDGET (userdata)); + +} + + +static void +user_widget_set_twin_item (UserWidget* self, + DbusmenuMenuitem* twin_item) +{ + UserWidgetPrivate* priv = USER_WIDGET_GET_PRIVATE(self); + priv->twin_item = twin_item; + g_signal_connect( G_OBJECT(priv->twin_item), "property-changed", + G_CALLBACK(user_widget_property_update), self); + +} + + /** + * transport_new: + * @returns: a new #UserWidget. + **/ +GtkWidget* +user_widget_new(DbusmenuMenuitem *item) +{ + GtkWidget* widget = g_object_new(USER_WIDGET_TYPE, NULL); + user_widget_set_twin_item ( USER_WIDGET(widget), item ); + return widget; +} diff --git a/src/user-widget.h b/src/user-widget.h new file mode 100644 index 0000000..e1f6d1a --- /dev/null +++ b/src/user-widget.h @@ -0,0 +1,54 @@ +/* +Copyright 2011 Canonical Ltd. + +Authors: + Conor Curran <conor.curran@canonical.com> + +This program is free software: you can redistribute it and/or modify it +under the terms of the GNU General Public License version 3, as published +by the Free Software Foundation. + +This program is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranties of +MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR +PURPOSE. See the GNU General Public License for more details. + +You should have received a copy of the GNU General Public License along +with this program. If not, see <http://www.gnu.org/licenses/>. +*/ +#ifndef __USER_WIDGET_H__ +#define __USER_WIDGET_H__ + +#include <gtk/gtk.h> +#if GTK_CHECK_VERSION(3, 0, 0) +#include <libdbusmenu-gtk3/menuitem.h> +#else +#include <libdbusmenu-gtk/menuitem.h> +#endif + +G_BEGIN_DECLS + +#define USER_WIDGET_TYPE (user_widget_get_type ()) +#define USER_WIDGET(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), USER_WIDGET_TYPE, UserWidget)) +#define USER_WIDGET_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), USER_WIDGET_TYPE, UserWidgetClass)) +#define IS_USER_WIDGET(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), USER_WIDGET_TYPE)) +#define IS_USER_WIDGET_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), USER_WIDGET_TYPE)) +#define USER_WIDGET_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), USER_WIDGET_TYPE, UserWidgetClass)) + +typedef struct _UserWidget UserWidget; +typedef struct _UserWidgetClass UserWidgetClass; + +struct _UserWidgetClass { + GtkMenuItemClass parent_class; +}; + +struct _UserWidget { + GtkMenuItem parent; +}; + +GType user_widget_get_type (void); +GtkWidget* user_widget_new(DbusmenuMenuitem *twin_item); + +G_END_DECLS + +#endif |