diff --git configure.ac configure.ac index eb90e68..306f3aa 100644 --- configure.ac +++ configure.ac @@ -70,6 +70,31 @@ AM_CONDITIONAL(HAVE_LIBCANBERRA_GTK, test "x$CANBERRA_GTK" = "x1") AM_CONDITIONAL(HAVE_TYPING_BREAK, test "x$TYPING_BREAK" = xtyping-break) +dnl app indicator +APPINDICATOR_REQUIRED=0.0.7 + +AC_ARG_ENABLE(appindicator, + AS_HELP_STRING([--enable-appindicator[=@<:@no/auto/yes@:>@]],[Build support for application indicators ]), + [enable_appindicator=$enableval], + [enable_appindicator="auto"]) + +if test x$enable_appindicator = xauto ; then + PKG_CHECK_EXISTS([appindicator-0.1 >= $APPINDICATOR_REQUIRED], + enable_appindicator="yes", + enable_appindicator="no") +fi + +if test x$enable_appindicator = xyes ; then + PKG_CHECK_EXISTS([appindicator-0.1 >= $APPINDICATOR_REQUIRED],, + AC_MSG_ERROR([appindicator-0.1 is not installed])) + PKG_CHECK_MODULES(APP_INDICATOR, + appindicator-0.1 >= $APPINDICATOR_REQUIRED) + AC_SUBST(APP_INDICATOR_CFLAGS) + AC_SUBST(APP_INDICATOR_LIBS) + AC_DEFINE(HAVE_APP_INDICATOR, 1, [Have AppIndicator]) +fi +AM_CONDITIONAL(HAVE_APP_INDICATOR, test x"$enable_appindicator" = xyes) + dnl keyboard-properties-capplet savecppflags=$CPPFLAGS CPPFLAGS="$CPPFLAGS $X_CFLAGS" diff --git typing-break/Makefile.am typing-break/Makefile.am index f1b89bf..c03e604 100644 --- typing-break/Makefile.am +++ typing-break/Makefile.am @@ -30,6 +30,11 @@ if HAVE_LIBCANBERRA_GTK gnome_typing_monitor_LDADD += @LIBCANBERRA_GTK_LIBS@ endif +if HAVE_APP_INDICATOR + gnome_typing_monitor_CFLAGS += -DHAVE_APP_INDICATOR @APP_INDICATOR_CFLAGS@ + gnome_typing_monitor_LDADD += @APP_INDICATOR_LIBS@ +endif + imagedir = $(pkgdatadir)/pixmaps dist_image_DATA = bar.png bar-red.png bar-green.png bar-disabled.png ocean-stripes.png diff --git typing-break/drwright.c typing-break/drwright.c index 9c7c2a0..3b8282b 100644 --- typing-break/drwright.c +++ typing-break/drwright.c @@ -29,6 +29,10 @@ #include #include +#ifdef HAVE_APP_INDICATOR +#include +#endif + #include "drwright.h" #include "drw-break-window.h" #include "drw-monitor.h" @@ -52,6 +56,11 @@ typedef enum { STATE_BREAK_DONE } DrwState; +#ifdef HAVE_APP_INDICATOR +#define TYPING_MONITOR_ACTIVE_ICON "bar-green" +#define TYPING_MONITOR_ATTENTION_ICON "bar-red" +#endif + struct _DrWright { /* Widgets. */ GtkWidget *break_window; @@ -80,6 +89,9 @@ struct _DrWright { gboolean blink_on; +#ifdef HAVE_APP_INDICATOR + AppIndicator *indicator; +#else GtkStatusIcon *icon; GdkPixbuf *neutral_bar; @@ -87,6 +99,7 @@ struct _DrWright { GdkPixbuf *green_bar; GdkPixbuf *disabled_bar; GdkPixbuf *composite_bar; +#endif GtkWidget *warn_dialog; }; @@ -94,7 +107,12 @@ struct _DrWright { static void activity_detected_cb (DrwMonitor *monitor, DrWright *drwright); static gboolean maybe_change_state (DrWright *drwright); +static gint get_time_left (DrWright *drwright); +#ifdef HAVE_APP_INDICATOR +static gboolean update_menu_text (DrWright *drwright); +#else static gboolean update_tooltip (DrWright *drwright); +#endif static void break_window_done_cb (GtkWidget *window, DrWright *dr); static void break_window_postpone_cb (GtkWidget *window, @@ -107,7 +125,11 @@ static void popup_preferences_cb (GtkAction *action, DrWright *dr); static void popup_about_cb (GtkAction *action, DrWright *dr); +#ifdef HAVE_APP_INDICATOR +static void init_app_indicator (DrWright *dr); +#else static void init_tray_icon (DrWright *dr); +#endif static GList * create_secondary_break_windows (void); static const GtkActionEntry actions[] = { @@ -126,6 +148,31 @@ setup_debug_values (DrWright *dr) dr->break_time = 10; } +#ifdef HAVE_APP_INDICATOR +static void +update_app_indicator (DrWright *dr) +{ + AppIndicatorStatus new_status; + + if (!dr->enabled) { + app_indicator_set_status (dr->indicator, + APP_INDICATOR_STATUS_PASSIVE); + return; + } + + switch (dr->state) { + case STATE_WARN: + case STATE_BREAK_SETUP: + case STATE_BREAK: + new_status = APP_INDICATOR_STATUS_ATTENTION; + break; + default: + new_status = APP_INDICATOR_STATUS_ACTIVE; + } + + app_indicator_set_status (dr->indicator, new_status); +} +#else static void update_icon (DrWright *dr) { @@ -208,6 +255,7 @@ update_icon (DrWright *dr) dr->composite_bar = tmp_pixbuf; } +#endif static gboolean blink_timeout_cb (DrWright *dr) @@ -222,6 +270,7 @@ blink_timeout_cb (DrWright *dr) timeout = BLINK_TIMEOUT_MIN; } +#ifndef HAVE_APP_INDICATOR if (dr->blink_on || timeout == 0) { gtk_status_icon_set_from_pixbuf (dr->icon, dr->composite_bar); @@ -229,6 +278,7 @@ blink_timeout_cb (DrWright *dr) gtk_status_icon_set_from_pixbuf (dr->icon, dr->neutral_bar); } +#endif dr->blink_on = !dr->blink_on; @@ -317,8 +367,10 @@ maybe_change_state (DrWright *dr) dr->break_window = NULL; } +#ifndef HAVE_APP_INDICATOR gtk_status_icon_set_from_pixbuf (dr->icon, dr->neutral_bar); +#endif dr->save_last_time = 0; @@ -329,7 +381,11 @@ maybe_change_state (DrWright *dr) dr->state = STATE_RUNNING; } +#ifdef HAVE_APP_INDICATOR + update_menu_text (dr); +#else update_tooltip (dr); +#endif stop_blinking (dr); break; @@ -356,8 +412,10 @@ maybe_change_state (DrWright *dr) } stop_blinking (dr); +#ifndef HAVE_APP_INDICATOR gtk_status_icon_set_from_pixbuf (dr->icon, dr->red_bar); +#endif drw_timer_start (dr->timer); @@ -398,8 +456,10 @@ maybe_change_state (DrWright *dr) case STATE_BREAK_DONE_SETUP: stop_blinking (dr); +#ifndef HAVE_APP_INDICATOR gtk_status_icon_set_from_pixbuf (dr->icon, dr->green_bar); +#endif dr->state = STATE_BREAK_DONE; break; @@ -415,15 +475,53 @@ maybe_change_state (DrWright *dr) dr->last_elapsed_time = elapsed_time; +#ifdef HAVE_APP_INDICATOR + update_app_indicator (dr); +#else update_icon (dr); +#endif return TRUE; } +#ifdef HAVE_APP_INDICATOR +static gboolean +update_menu_text (DrWright *dr) +{ + const gchar normal_msg_template[] = "Take a break now (next in %dm)"; + const gchar less_than_one_msg_template[] = "Take a break now (next in less than one minute)"; + + gint min; + gchar *str; + GtkWidget *item; + + if (!dr->enabled) { + app_indicator_set_status (dr->indicator, + APP_INDICATOR_STATUS_PASSIVE); + return TRUE; + } + + min = get_time_left (dr); + + if (min >= 1) { + str = g_strdup_printf (_(normal_msg_template), min); + } else { + str = g_strdup_printf (_(less_than_one_msg_template)); + } + + /* set menu text */ + item = gtk_ui_manager_get_widget(dr->ui_manager, "/Pop/TakeABreak"); + gtk_menu_item_set_label (GTK_MENU_ITEM (item), str); + + g_free (str); + + return TRUE; +} +#else static gboolean update_tooltip (DrWright *dr) { - gint elapsed_time, min; + gint min; gchar *str; if (!dr->enabled) { @@ -432,9 +530,7 @@ update_tooltip (DrWright *dr) return TRUE; } - elapsed_time = drw_timer_elapsed (dr->timer); - - min = floor (0.5 + (dr->type_time - elapsed_time - dr->save_last_time) / 60.0); + min = get_time_left (dr); if (min >= 1) { str = g_strdup_printf (ngettext("%d minute until the next break", @@ -451,6 +547,17 @@ update_tooltip (DrWright *dr) return TRUE; } +#endif + +static gint +get_time_left (DrWright *dr) +{ + gint elapsed_time; + + elapsed_time = drw_timer_elapsed (dr->timer); + + return floor (0.5 + (dr->type_time - elapsed_time - dr->save_last_time) / 60.0); +} static void activity_detected_cb (DrwMonitor *monitor, @@ -491,7 +598,11 @@ gconf_notify_cb (GConfClient *client, "/Pop/TakeABreak"); gtk_widget_set_sensitive (item, dr->enabled); +#ifdef HAVE_APP_INDICATOR + update_menu_text (dr); +#else update_tooltip (dr); +#endif } } @@ -557,6 +668,7 @@ popup_about_cb (GtkAction *action, DrWright *dr) NULL); } +#ifndef HAVE_APP_INDICATOR static void popup_menu_cb (GtkWidget *widget, guint button, @@ -575,6 +687,7 @@ popup_menu_cb (GtkWidget *widget, 0, gtk_get_current_event_time()); } +#endif static void break_window_done_cb (GtkWidget *window, @@ -585,7 +698,11 @@ break_window_done_cb (GtkWidget *window, dr->state = STATE_BREAK_DONE_SETUP; dr->break_window = NULL; +#ifdef HAVE_APP_INDICATOR + update_menu_text (dr); +#else update_tooltip (dr); +#endif maybe_change_state (dr); } @@ -613,8 +730,13 @@ break_window_postpone_cb (GtkWidget *window, drw_timer_start (dr->timer); maybe_change_state (dr); +#ifdef HAVE_APP_INDICATOR + update_menu_text (dr); + update_app_indicator (dr); +#else update_icon (dr); update_tooltip (dr); +#endif } static void @@ -631,6 +753,33 @@ break_window_destroy_cb (GtkWidget *window, dr->secondary_break_windows = NULL; } +#ifdef HAVE_APP_INDICATOR +static void +init_app_indicator (DrWright *dr) +{ + GtkWidget *indicator_menu; + + dr->indicator = + app_indicator_new_with_path ("typing-break-indicator", + TYPING_MONITOR_ACTIVE_ICON, + APP_INDICATOR_CATEGORY_APPLICATION_STATUS, + IMAGEDIR); + if (dr->enabled) { + app_indicator_set_status (dr->indicator, + APP_INDICATOR_STATUS_ACTIVE); + } else { + app_indicator_set_status (dr->indicator, + APP_INDICATOR_STATUS_PASSIVE); + } + + indicator_menu = gtk_ui_manager_get_widget (dr->ui_manager, "/Pop"); + app_indicator_set_menu (dr->indicator, GTK_MENU (indicator_menu)); + app_indicator_set_attention_icon (dr->indicator, TYPING_MONITOR_ATTENTION_ICON); + + update_menu_text (dr); + update_app_indicator (dr); +} +#else static void init_tray_icon (DrWright *dr) { @@ -644,6 +793,7 @@ init_tray_icon (DrWright *dr) G_CALLBACK (popup_menu_cb), dr); } +#endif static GList * create_secondary_break_windows (void) @@ -758,6 +908,12 @@ drwright_new (void) G_CALLBACK (activity_detected_cb), dr); +#ifdef HAVE_APP_INDICATOR + init_app_indicator (dr); + g_timeout_add_seconds (12, + (GSourceFunc) update_menu_text, + dr); +#else dr->neutral_bar = gdk_pixbuf_new_from_file (IMAGEDIR "/bar.png", NULL); dr->red_bar = gdk_pixbuf_new_from_file (IMAGEDIR "/bar-red.png", NULL); dr->green_bar = gdk_pixbuf_new_from_file (IMAGEDIR "/bar-green.png", NULL); @@ -768,6 +924,7 @@ drwright_new (void) g_timeout_add_seconds (12, (GSourceFunc) update_tooltip, dr); +#endif g_timeout_add_seconds (1, (GSourceFunc) maybe_change_state, dr); diff --git typing-break/main.c typing-break/main.c index 30f5c3e..723e222 100644 --- typing-break/main.c +++ typing-break/main.c @@ -95,6 +95,7 @@ main (int argc, char *argv[]) return 0; } +#ifndef HAVE_APP_INDICATOR if (!no_check && !have_tray ()) { GtkWidget *dialog; @@ -112,6 +113,7 @@ main (int argc, char *argv[]) gtk_widget_destroy (dialog); } +#endif drwright = drwright_new ();