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;
}
Example #6
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;
		}

		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;
}
Example #7
0
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);
}