diff --git a/src/LoginManager.vala b/daemon/DBusService.vala similarity index 77% rename from src/LoginManager.vala rename to daemon/DBusService.vala index ac0055d..125cc3a 100644 --- a/src/LoginManager.vala +++ b/daemon/DBusService.vala @@ -1,5 +1,5 @@ /* -* Copyright (c) 2020 Marco Betschart (https://marco.betschart.name) +* Copyright (c) 2021 Marco Betschart (https://marco.betschart.name) * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public @@ -19,7 +19,7 @@ * Authored by: Marco Betschart { + debug ("Aquired DBus connection named '%s'", name); + try { + timelimit_dbus_service_registration_id = connection.register_object ("/com/github/marbetschar/timelimit", timelimit_dbus_service); + } catch (GLib.Error e) { + critical ("Error while aquiring DBus connection named '%s': %s", name, e.message); + } + }, + () => {}, + (connection, name) => { + if (timelimit_dbus_service_registration_id != 0) { + connection.unregister_object (timelimit_dbus_service_registration_id); + timelimit_dbus_service_registration_id = 0; + + } + critical ("Could not aquire DBus connection named '%s', or the connection was closed.", name); + } + ); + } + + private void on_timelimit_alert_datetime_changed () { + if (alert_timeout > 0) { + debug ("on_timelimit_alert_datetime_changed: Removing scheduled notification."); + GLib.Source.remove (alert_timeout); + alert_timeout = 0; + } + + var now = new GLib.DateTime.now_local (); + var alert_datetime = now; + if (timelimit_dbus_service.alert_datetime_iso8601 != "") { + alert_datetime = new GLib.DateTime.from_iso8601 (timelimit_dbus_service.alert_datetime_iso8601, null); + } + + var seconds_remaining = alert_datetime.difference (now) / 1000000; + if (seconds_remaining > 0) { + debug ("on_timelimit_alert_datetime_changed: Schedule notification for: %s", timelimit_dbus_service.alert_datetime_iso8601); + + alert_timeout = GLib.Timeout.add_seconds ((uint) seconds_remaining, () => { + var notification = new Notification (_("It's time!")); + notification.set_body (_("Your time limit is over.")); + notification.set_priority (NotificationPriority.URGENT); + + send_notification ("com.github.marbetschar.time-limit", notification); + + return GLib.Source.REMOVE; + }); + } + } + + protected override void activate () { + Gtk.main (); + } + } + + public static int main (string[] args) { + OptionContext context = new OptionContext (""); + context.add_main_entries (OPTIONS, null); + + try { + context.parse (ref args); + } catch (OptionError e) { + error (e.message); + } + + Granite.Services.Logger.initialize ("TimeLimit"); + Granite.Services.Logger.DisplayLevel = Granite.Services.LogLevel.WARN; + + if (has_debug) { + Granite.Services.Logger.DisplayLevel = Granite.Services.LogLevel.DEBUG; + } + + var app = new Daemon (); + return app.run (args); + } +} \ No newline at end of file diff --git a/daemon/meson.build b/daemon/meson.build new file mode 100644 index 0000000..6af3273 --- /dev/null +++ b/daemon/meson.build @@ -0,0 +1,17 @@ +daemon_deps = [ + gio_dep, + glib_dep, + granite_dep, + m_dep +] + +executable( + meson.project_name()+'-daemon', + [ + 'Daemon.vala', + 'DBusService.vala' + ], + dependencies: daemon_deps, + install: true, + install_dir: join_paths(get_option('prefix'), get_option('libexecdir')) +) \ No newline at end of file diff --git a/data/com.github.marbetschar.time-limit-daemon.desktop.in b/data/com.github.marbetschar.time-limit-daemon.desktop.in new file mode 100644 index 0000000..f61fd9e --- /dev/null +++ b/data/com.github.marbetschar.time-limit-daemon.desktop.in @@ -0,0 +1,13 @@ +[Desktop Entry] +Name=Time Limit +Comment=Notify when time is up +Exec=@EXEC_PATH@ +Icon=com.github.marbetschar.time-limit +Terminal=false +Type=Application +Categories=System; +OnlyShowIn=Pantheon; +NoDisplay=true +X-GNOME-AutoRestart=true +X-GNOME-Autostart-Phase=Applications +X-GNOME-UsesNotifications=true diff --git a/data/meson.build b/data/meson.build index 79ac674..1dcbe74 100644 --- a/data/meson.build +++ b/data/meson.build @@ -11,6 +11,15 @@ foreach i : icon_sizes ) endforeach +desktop_config = configuration_data() +desktop_config.set('EXEC_PATH', libexecdir+'-daemon') +configure_file ( + input: meson.project_name()+'-daemon' + '.desktop.in', + output: meson.project_name()+'-daemon' + '.desktop', + configuration: desktop_config, + install_dir: join_paths(get_option('datadir'), 'applications') +) + i18n.merge_file( input: meson.project_name() + '.desktop.in', output: meson.project_name() + '.desktop', diff --git a/meson.build b/meson.build index 965f33c..6327255 100644 --- a/meson.build +++ b/meson.build @@ -10,6 +10,8 @@ add_project_arguments([ language: 'c' ) +libexecdir = join_paths(get_option('prefix'), get_option('libexecdir'), meson.project_name()) + asresources = gnome.compile_resources( 'as-resources', 'data/' + meson.project_name() + '.gresource.xml', @@ -17,12 +19,18 @@ asresources = gnome.compile_resources( c_name: 'as' ) +gio_dep = dependency('gio-2.0') +glib_dep = dependency('glib-2.0') +granite_dep = dependency('granite', version: '>=0.5') +m_dep = meson.get_compiler('c').find_library('m', required : false) + dependencies = [ - dependency('glib-2.0'), + gio_dep, + glib_dep, + granite_dep, dependency('gtk+-3.0'), - dependency('granite', version: '>=0.5'), dependency('libhandy-1', version: '>=0.83.0'), - meson.get_compiler('c').find_library('m', required : false) + m_dep ] subdir('src') @@ -36,6 +44,7 @@ executable( ) subdir('data') +subdir('daemon') subdir('po') meson.add_install_script('meson/post_install.py') diff --git a/po/POTFILES b/po/POTFILES index 3666bd9..4d02dff 100644 --- a/po/POTFILES +++ b/po/POTFILES @@ -1 +1,12 @@ +daemon/Daemon.vala +daemon/DBusService.vala src/Widgets/Clock.vala +src/Widgets/Face.vala +src/Widgets/Labels.vala +src/Widgets/ProgressArrow.vala +src/Widgets/ProgressBar.vala +src/Widgets/ProgressIndicator.vala +src/Application.vala +src/DBusService.vala +src/MainWindow.vala +src/Uitl.vala diff --git a/src/Application.vala b/src/Application.vala index 2694393..1ea39d3 100644 --- a/src/Application.vala +++ b/src/Application.vala @@ -19,7 +19,7 @@ * Authored by: Marco Betschart { - send_notification("com.github.marbetschar.time-limit", notification); - }); - var granite_settings = Granite.Settings.get_default (); var gtk_settings = Gtk.Settings.get_default (); diff --git a/src/DBusService.vala b/src/DBusService.vala new file mode 100644 index 0000000..475f401 --- /dev/null +++ b/src/DBusService.vala @@ -0,0 +1,25 @@ +/* +* Copyright (c) 2021 Marco Betschart (https://marco.betschart.name) +* +* This program is free software; you can redistribute it and/or +* modify it under the terms of the GNU General Public +* License as published by the Free Software Foundation; either +* version 2 of the License, or (at your option) any later version. +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY 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, write to the +* Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, +* Boston, MA 02110-1301 USA +* +* Authored by: Marco Betschart { @@ -77,17 +76,17 @@ public class Timer.MainWindow : Hdy.ApplicationWindow { configure_id = 0; if (is_maximized) { - Timer.Application.settings.set_boolean ("window-maximized", true); + TimeLimit.Application.settings.set_boolean ("window-maximized", true); } else { - Timer.Application.settings.set_boolean ("window-maximized", false); + TimeLimit.Application.settings.set_boolean ("window-maximized", false); Gdk.Rectangle rect; get_allocation (out rect); - Timer.Application.settings.set ("window-size", "(ii)", rect.width, rect.height); + TimeLimit.Application.settings.set ("window-size", "(ii)", rect.width, rect.height); int root_x, root_y; get_position (out root_x, out root_y); - Timer.Application.settings.set ("window-position", "(ii)", root_x, root_y); + TimeLimit.Application.settings.set ("window-position", "(ii)", root_x, root_y); } return Source.REMOVE; diff --git a/src/Util.vala b/src/Util.vala index 92d4da3..48e8b65 100644 --- a/src/Util.vala +++ b/src/Util.vala @@ -19,7 +19,7 @@ * Authored by: Marco Betschart { - if (start) { - if (update_labels_timeout_id > 0) { - GLib.Source.remove (update_labels_timeout_id); - update_labels_timeout_id = 0; - } - suspend_datetime = new GLib.DateTime.now_local (); - GLib.Timeout.add_seconds (1, on_resume); - } - }); - } catch(IOError e) { - warning (e.message); + timelimit_dbus_service = Bus.get_proxy_sync ( + BusType.SESSION, + "com.github.marbetschar.TimeLimit", + "/com/github/marbetschar/timelimit" + ); + debug ("Connected to timelimit dbus service."); + + } catch (Error e) { + critical ("Connecting to timelimit dbus service failed: %s", e.message); } update_labels (); + + if (timelimit_dbus_service != null && timelimit_dbus_service.alert_datetime_iso8601 != null && timelimit_dbus_service.alert_datetime_iso8601 != "") { + debug ("Retrieving alert datetime from daemon: %s", timelimit_dbus_service.alert_datetime_iso8601); + + var alert_datetime = new GLib.DateTime.from_iso8601 (timelimit_dbus_service.alert_datetime_iso8601, null); + var now = new GLib.DateTime.now_local (); + + var seconds_remaining = alert_datetime.difference (now) / 1000000; + if (seconds_remaining > 0) { + seconds = seconds_remaining; + on_pause_changed (); + + GLib.Idle.add (() => { + indicator.notify_property ("progress"); + return GLib.Source.REMOVE; + }); + } + } } private bool header_handles_event (Gdk.EventButton event) { @@ -175,12 +188,6 @@ public class Timer.Widgets.Clock : Gtk.Overlay { update_labels (); if (seconds <= 0) { - var main_window = (Timer.MainWindow) parent.parent; - var notification = new Notification (_("It's time!")); - notification.set_body (_("Your time limit is over.")); - notification.set_priority (NotificationPriority.URGENT); - main_window.send_notification (notification); - Granite.Services.Application.set_progress_visible.begin (false); } } @@ -191,6 +198,7 @@ public class Timer.Widgets.Clock : Gtk.Overlay { seconds = convert_progress_to_seconds (progress); progress_total_seconds = seconds; + update_labels (); } } @@ -203,21 +211,21 @@ public class Timer.Widgets.Clock : Gtk.Overlay { } return !pause && seconds > 0; }); - } - update_labels (); - } - private bool on_resume () { - if (!pause && suspend_datetime != null) { - var now = new GLib.DateTime.now_local (); - var sleep_seconds = now.difference (suspend_datetime) / 1000000; - suspend_datetime = null; + if (timelimit_dbus_service != null) { + var alert_datetime = new GLib.DateTime.now_local (); + alert_datetime = alert_datetime.add_seconds (seconds); + var alert_datetime_iso8601 = alert_datetime.format_iso8601 (); + + debug ("Schedule notification for: %s", alert_datetime_iso8601); + timelimit_dbus_service.alert_datetime_iso8601 = alert_datetime_iso8601; + } - seconds = GLib.Math.fmax(0, seconds - sleep_seconds); } else { - update_labels (); + debug ("Remove scheduled notification"); + timelimit_dbus_service.alert_datetime_iso8601 = ""; } - return GLib.Source.REMOVE; + update_labels (); } private bool update_labels () { @@ -237,7 +245,7 @@ public class Timer.Widgets.Clock : Gtk.Overlay { } else { labels.minutes_label.label = "%i\'".printf ((int) convert_seconds_to_minutes (seconds)); - labels.seconds_label.label = "%i\"".printf ((int) Timer.Util.truncating_remainder (seconds, 60)); + labels.seconds_label.label = "%i\"".printf ((int) TimeLimit.Util.truncating_remainder (seconds, 60)); } if (!button_press_active && pause && seconds > 0) { @@ -263,9 +271,9 @@ public class Timer.Widgets.Clock : Gtk.Overlay { var seconds = Math.round (scaled_progress * 60.0 * 60.0); if (seconds <= 300) { - seconds = seconds - Timer.Util.truncating_remainder (seconds, 10); + seconds = seconds - TimeLimit.Util.truncating_remainder (seconds, 10); } else { - seconds = seconds - Timer.Util.truncating_remainder (seconds, 60); + seconds = seconds - TimeLimit.Util.truncating_remainder (seconds, 60); } return seconds; diff --git a/src/Widgets/Face.vala b/src/Widgets/Face.vala index 4074402..cbb3b87 100644 --- a/src/Widgets/Face.vala +++ b/src/Widgets/Face.vala @@ -19,7 +19,7 @@ * Authored by: Marco Betschart 0.25) { progress_new += 1; diff --git a/src/Widgets/ProgressBar.vala b/src/Widgets/ProgressBar.vala index b7e82bf..59619b8 100644 --- a/src/Widgets/ProgressBar.vala +++ b/src/Widgets/ProgressBar.vala @@ -19,7 +19,7 @@ * Authored by: Marco Betschart