static gboolean blink_timeout_cb (DrWright *dr) { gfloat r; gint timeout; r = (dr->type_time - drw_timer_elapsed (dr->timer) - dr->save_last_time) / dr->warn_time; timeout = BLINK_TIMEOUT + BLINK_TIMEOUT_FACTOR * r; if (timeout < BLINK_TIMEOUT_MIN) { timeout = BLINK_TIMEOUT_MIN; } if (dr->blink_on || timeout == 0) { gtk_status_icon_set_from_pixbuf (dr->icon, dr->composite_bar); } else { gtk_status_icon_set_from_pixbuf (dr->icon, dr->neutral_bar); } dr->blink_on = !dr->blink_on; if (timeout) { dr->blink_timeout_id = g_timeout_add (timeout, (GSourceFunc) blink_timeout_cb, dr); } else { dr->blink_timeout_id = 0; } return FALSE; }
static void break_window_postpone_cb (GtkWidget *window, DrWright *dr) { gint elapsed_time; gtk_widget_destroy (dr->break_window); dr->state = STATE_RUNNING; dr->break_window = NULL; elapsed_time = drw_timer_elapsed (dr->timer); if (elapsed_time + dr->save_last_time >= dr->type_time) { /* Typing time has expired, but break was postponed. * We'll warn again in (elapsed * sqrt (typing_time))^2 */ gfloat postpone_time = (((float) elapsed_time) / dr->break_time) * sqrt (dr->type_time); postpone_time *= postpone_time; dr->save_last_time = dr->type_time - MAX (dr->warn_time, (gint) postpone_time); } drw_timer_start (dr->timer); maybe_change_state (dr); update_status (dr); #ifdef HAVE_APP_INDICATOR update_app_indicator (dr); #else update_icon (dr); #endif /* HAVE_APP_INDICATOR */ }
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 gboolean maybe_change_state (DrWright *dr) { gint elapsed_time; gint elapsed_idle_time; if (debug) { drw_timer_start (dr->idle_timer); } elapsed_time = drw_timer_elapsed (dr->timer) + dr->save_last_time; elapsed_idle_time = drw_timer_elapsed (dr->idle_timer); if (elapsed_time > dr->last_elapsed_time + dr->warn_time) { /* If the timeout is delayed by the amount of warning time, then * we must have been suspended or stopped, so we just start * over. */ dr->state = STATE_START; } switch (dr->state) { case STATE_START: if (dr->break_window) { gtk_widget_destroy (dr->break_window); dr->break_window = NULL; } #ifndef HAVE_APP_INDICATOR gtk_status_icon_set_from_pixbuf (dr->icon, dr->neutral_bar); #endif /* HAVE_APP_INDICATOR */ dr->save_last_time = 0; drw_timer_start (dr->timer); drw_timer_start (dr->idle_timer); if (dr->enabled) { dr->state = STATE_RUNNING; } update_status (dr); stop_blinking (dr); break; case STATE_RUNNING: case STATE_WARN: if (elapsed_idle_time >= dr->break_time) { dr->state = STATE_BREAK_DONE_SETUP; } else if (elapsed_time >= dr->type_time) { dr->state = STATE_BREAK_SETUP; } else if (dr->state != STATE_WARN && elapsed_time >= dr->type_time - dr->warn_time) { dr->state = STATE_WARN; start_blinking (dr); } break; case STATE_BREAK_SETUP: /* Don't allow more than one break window to coexist, can happen * if a break is manually enforced. */ if (dr->break_window) { dr->state = STATE_BREAK; break; } stop_blinking (dr); #ifndef HAVE_APP_INDICATOR gtk_status_icon_set_from_pixbuf (dr->icon, dr->red_bar); #endif /* HAVE_APP_INDICATOR */ drw_timer_start (dr->timer); dr->break_window = drw_break_window_new (); g_signal_connect (dr->break_window, "map_event", G_CALLBACK (break_window_map_event_cb), dr); g_signal_connect (dr->break_window, "done", G_CALLBACK (break_window_done_cb), dr); g_signal_connect (dr->break_window, "postpone", G_CALLBACK (break_window_postpone_cb), dr); g_signal_connect (dr->break_window, "destroy", G_CALLBACK (break_window_destroy_cb), dr); dr->secondary_break_windows = create_secondary_break_windows (); gtk_widget_show (dr->break_window); dr->save_last_time = elapsed_time; dr->state = STATE_BREAK; break; case STATE_BREAK: if (elapsed_time - dr->save_last_time >= dr->break_time) { dr->state = STATE_BREAK_DONE_SETUP; } break; case STATE_BREAK_DONE_SETUP: stop_blinking (dr); #ifndef HAVE_APP_INDICATOR gtk_status_icon_set_from_pixbuf (dr->icon, dr->green_bar); #endif /* HAVE_APP_INDICATOR */ dr->state = STATE_BREAK_DONE; break; case STATE_BREAK_DONE: dr->state = STATE_START; if (dr->break_window) { gtk_widget_destroy (dr->break_window); dr->break_window = NULL; } break; } dr->last_elapsed_time = elapsed_time; #ifdef HAVE_APP_INDICATOR update_app_indicator (dr); #else update_icon (dr); #endif /* HAVE_APP_INDICATOR */ return TRUE; }
static void update_icon (DrWright *dr) { GdkPixbuf *pixbuf; GdkPixbuf *tmp_pixbuf; gint width, height; gfloat r; gint offset; gboolean set_pixbuf; if (!dr->enabled) { gtk_status_icon_set_from_pixbuf (dr->icon, dr->disabled_bar); return; } tmp_pixbuf = gdk_pixbuf_copy (dr->neutral_bar); width = gdk_pixbuf_get_width (tmp_pixbuf); height = gdk_pixbuf_get_height (tmp_pixbuf); set_pixbuf = TRUE; switch (dr->state) { case STATE_BREAK: case STATE_BREAK_SETUP: r = 1; break; case STATE_BREAK_DONE: case STATE_BREAK_DONE_SETUP: case STATE_START: r = 0; break; default: r = (float) (drw_timer_elapsed (dr->timer) + dr->save_last_time) / (float) dr->type_time; break; } offset = CLAMP ((height - 0) * (1.0 - r), 1, height - 0); switch (dr->state) { case STATE_WARN: pixbuf = dr->red_bar; set_pixbuf = FALSE; break; case STATE_BREAK_SETUP: case STATE_BREAK: pixbuf = dr->red_bar; break; default: pixbuf = dr->green_bar; } gdk_pixbuf_composite (pixbuf, tmp_pixbuf, 0, offset, width, height - offset, 0, 0, 1.0, 1.0, GDK_INTERP_BILINEAR, 255); if (set_pixbuf) { gtk_status_icon_set_from_pixbuf (dr->icon, tmp_pixbuf); } if (dr->composite_bar) { g_object_unref (dr->composite_bar); } dr->composite_bar = tmp_pixbuf; }
static gboolean maybe_change_state (DrWright *dr) { gint elapsed_time; gint elapsed_idle_time; if (debug) { drw_timer_start (dr->idle_timer); } elapsed_time = drw_timer_elapsed (dr->timer) + dr->save_last_time; elapsed_idle_time = drw_timer_elapsed (dr->idle_timer); if (elapsed_time > dr->last_elapsed_time + dr->warn_time) { /* If the timeout is delayed by the amount of warning time, then * we must have been suspended or stopped, so we just start * over. */ dr->state = STATE_START; } switch (dr->state) { case STATE_START: if (dr->break_window) { gtk_widget_destroy (dr->break_window); dr->break_window = NULL; } dr->save_last_time = 0; drw_timer_start (dr->timer); drw_timer_start (dr->idle_timer); show_warning_notification (dr, FALSE); if (dr->enabled) { dr->state = STATE_RUNNING; } break; case STATE_RUNNING: case STATE_WARN: if (elapsed_idle_time >= dr->break_time) { dr->state = STATE_BREAK_DONE_SETUP; } else if (elapsed_time >= dr->type_time) { dr->state = STATE_BREAK_SETUP; } else if (dr->state != STATE_WARN && elapsed_time >= dr->type_time - dr->warn_time) { dr->state = STATE_WARN; } if (dr->state == STATE_WARN) { show_warning_notification (dr, TRUE); } break; case STATE_BREAK_SETUP: /* Don't allow more than one break window to coexist, can happen * if a break is manually enforced. */ if (dr->break_window) { dr->state = STATE_BREAK; break; } show_warning_notification (dr, FALSE); drw_timer_start (dr->timer); dr->break_window = drw_break_window_new (drwright_can_lock_screen (dr)); drw_break_window_set_elapsed_idle_time (DRW_BREAK_WINDOW (dr->break_window), elapsed_idle_time); g_signal_connect (dr->break_window, "map_event", G_CALLBACK (break_window_map_event_cb), dr); g_signal_connect (dr->break_window, "done", G_CALLBACK (break_window_done_cb), dr); g_signal_connect (dr->break_window, "postpone", G_CALLBACK (break_window_postpone_cb), dr); g_signal_connect (dr->break_window, "lock", G_CALLBACK (break_window_lock_cb), dr); g_signal_connect (dr->break_window, "destroy", G_CALLBACK (break_window_destroy_cb), dr); dr->secondary_break_windows = create_secondary_break_windows (); gtk_widget_show (dr->break_window); dr->save_last_time = elapsed_time; dr->state = STATE_BREAK; break; case STATE_BREAK: if (elapsed_time - dr->save_last_time >= dr->break_time) { dr->state = STATE_BREAK_DONE_SETUP; } break; case STATE_BREAK_DONE_SETUP: dr->state = STATE_BREAK_DONE; break; case STATE_BREAK_DONE: dr->state = STATE_START; if (dr->break_window) { gtk_widget_destroy (dr->break_window); dr->break_window = NULL; } break; } dr->last_elapsed_time = elapsed_time; return TRUE; }
static void show_warning_notification (DrWright *dr, gboolean show) { NotifyNotification *notification; gint minutes, seconds; gchar *summary, *body; GError *error = NULL; if (show == FALSE) { if (dr->notification) { gboolean success = notify_notification_close (dr->notification, &error); if (success) { g_object_unref (dr->notification); dr->notification = NULL; } else { g_warning ("%s", error->message); } g_clear_error (&error); } dr->num_minutes_last_displayed = -1; return; } seconds = dr->type_time - drw_timer_elapsed (dr->timer) - dr->save_last_time; minutes = (seconds / 60) + 1; if (minutes == dr->num_minutes_last_displayed) { return; } dr->num_minutes_last_displayed = minutes; summary = _("Typing Break Reminder"); if (minutes > 1) { body = g_strdup_printf (ngettext ("Approximately %d minute to the next break.", "Approximately %d minutes to the next break.", minutes), minutes); } else { body = g_strdup (_("Less than one minute to the next break.")); } if (dr->notification) { notification = dr->notification; notify_notification_update (notification, summary, body, "typing-monitor"); } else { notification = notify_notification_new (summary, body, "typing-monitor"); notify_notification_set_hint (notification, "resident", g_variant_new_boolean (TRUE)); notify_notification_add_action (notification, "settings", _("Settingsā¦"), NOTIFY_ACTION_CALLBACK (notification_action_cb), dr, NULL); notify_notification_add_action (notification, "take-break", _("Take Break Now"), NOTIFY_ACTION_CALLBACK (notification_action_cb), dr, NULL); dr->notification = notification; } if (!notify_notification_show (notification, &error)) { g_warning ("%s", error->message); } g_clear_error (&error); g_free (body); }