[gnome-break-timer/dylanmccall/meson-build: 14/25] Implement MutterActivityMonitorBackend



commit a77cf13e88983adf2e12088dead5e6ce8db5849a
Author: Dylan McCall <dylan dylanmccall com>
Date:   Wed Jan 9 23:11:26 2019 -0800

    Implement MutterActivityMonitorBackend

 common/IBreakHelper.vala                           |  12 +--
 flatpak/org.gnome.BreakTimer.json                  |   2 +
 gnome-break-timer.doap                             |   4 +-
 helper/SessionStatus.vala                          |   9 +-
 helper/activity-monitor/ActivityMonitor.vala       |  41 ++++----
 .../MutterActivityMonitorBackend.vala              | 108 +++++++++++++++++++++
 helper/break/TimerBreakController.vala             |   7 +-
 helper/util/Util.vala                              |   8 ++
 8 files changed, 155 insertions(+), 36 deletions(-)
---
diff --git a/common/IBreakHelper.vala b/common/IBreakHelper.vala
index 32b4503..bce0856 100644
--- a/common/IBreakHelper.vala
+++ b/common/IBreakHelper.vala
@@ -20,16 +20,16 @@ namespace BreakTimer {
 [DBus (name = "org.gnome.BreakTimer")]
 public interface IBreakHelper : Object {
        /** Returns the ID of the break that is currently focused and activated, if any. */
-       public abstract string? get_current_active_break () throws IOError;
+       public abstract string? get_current_active_break () throws DBusError, IOError;
 
        /** Returns a list of breaks that are currently known to the break helper. */
-       public abstract string[] get_break_ids () throws IOError;
+       public abstract string[] get_break_ids () throws DBusError, IOError;
 
        /** Returns a list of helpful status messages for each break, for debugging. */
-       public abstract string[] get_status_messages () throws IOError;
+       public abstract string[] get_status_messages () throws DBusError, IOError;
 
        /** Activate the specified break immediately, regardless of the usual activation conditions. */
-       public abstract void activate_break (string break_id) throws IOError;
+       public abstract void activate_break (string break_id) throws DBusError, IOError;
 
        // TODO: It might make sense to communicate when the active break changes,
        // using a signal. The only reason we don't at the moment is it adds
@@ -40,10 +40,10 @@ public interface IBreakHelper : Object {
 [DBus (name = "org.gnome.BreakTimer.TimerBreak")]
 public interface IBreakHelper_TimerBreak : Object {
        /** Get the break's current status, such as time remaining, or time until the break starts */
-       public abstract TimerBreakStatus get_status () throws IOError;
+       public abstract TimerBreakStatus get_status () throws DBusError, IOError;
 
        /** Activate the break */
-       public abstract void activate () throws IOError;
+       public abstract void activate () throws DBusError, IOError;
 }
 
 public struct BreakStatus {
diff --git a/flatpak/org.gnome.BreakTimer.json b/flatpak/org.gnome.BreakTimer.json
index 83285f4..5126de0 100644
--- a/flatpak/org.gnome.BreakTimer.json
+++ b/flatpak/org.gnome.BreakTimer.json
@@ -16,6 +16,8 @@
         "--talk-name=org.gnome.BreakTimer",
         "--own-name=org.gnome.BreakTimer.*",
         "--talk-name=org.gnome.BreakTimer.*",
+        "--talk-name=org.gnome.Mutter.IdleMonitor",
+        "--talk-name=org.freedesktop.Notifications",
         "--talk-name=ca.desrt.dconf",
         "--env=DCONF_USER_CONFIG_DIR=.config/dconf"
     ],
diff --git a/gnome-break-timer.doap b/gnome-break-timer.doap
index be29641..d46b77f 100644
--- a/gnome-break-timer.doap
+++ b/gnome-break-timer.doap
@@ -8,8 +8,6 @@
   <shortdesc xml:lang="en">Take a break</shortdesc>
   <homepage rdf:resource="https://wiki.gnome.org/Apps/GnomeBreakTimer"; />
 
-  <category rdf:resource="http://api.gnome.org/doap-extensions#desktop"; />
-
   <maintainer>
     <foaf:Person>
       <foaf:name>Dylan McCall</foaf:name>
@@ -24,4 +22,4 @@
       <gnome:userid>jstpierre</gnome:userid>
     </foaf:Person>
   </maintainer>
-</Project>
+</Project>
\ No newline at end of file
diff --git a/helper/SessionStatus.vala b/helper/SessionStatus.vala
index ab4b69d..02c99c6 100644
--- a/helper/SessionStatus.vala
+++ b/helper/SessionStatus.vala
@@ -19,12 +19,13 @@ namespace BreakTimer.Helper {
 
 [DBus (name = "org.gnome.ScreenSaver")]
 public interface IScreenSaver : Object {
+    public abstract bool get_active () throws DBusError, IOError;
+    public abstract uint32 get_active_time () throws DBusError, IOError;
+    public abstract void lock () throws DBusError, IOError;
+    public abstract void set_active (bool active) throws DBusError, IOError;
+
     public signal void active_changed (bool active);
 
-    public abstract bool get_active () throws IOError;
-    public abstract uint32 get_active_time () throws IOError;
-    public abstract void lock () throws IOError;
-    public abstract void set_active (bool active) throws IOError;
 }
 
 /**
diff --git a/helper/activity-monitor/ActivityMonitor.vala b/helper/activity-monitor/ActivityMonitor.vala
index df4d489..41ff270 100644
--- a/helper/activity-monitor/ActivityMonitor.vala
+++ b/helper/activity-monitor/ActivityMonitor.vala
@@ -28,13 +28,13 @@ public class ActivityMonitor : Object {
 
        public struct UserActivity {
                public ActivityType type;
-               public int idle_time;
-               public int time_since_active;
-               public int time_correction;
+               public int64 idle_time;
+               public int64 time_since_active;
+               public int64 time_correction;
 
                public Json.Object serialize () {
                        Json.Object json_root = new Json.Object ();
-                       json_root.set_int_member ("type", (int)this.type);
+                       json_root.set_int_member ("type", (int) this.type);
                        json_root.set_int_member ("idle_time", this.idle_time);
                        json_root.set_int_member ("time_since_active", this.time_since_active);
                        json_root.set_int_member ("time_correction", this.time_correction);
@@ -43,10 +43,10 @@ public class ActivityMonitor : Object {
 
                public static UserActivity deserialize (ref Json.Object json_root) {
                        return UserActivity () {
-                               type = (ActivityType)json_root.get_int_member ("type"),
-                               idle_time = (int)json_root.get_int_member ("idle_time"),
-                               time_since_active = (int)json_root.get_int_member ("time_since_active"),
-                               time_correction = (int)json_root.get_int_member ("time_correction")
+                               type = (ActivityType) json_root.get_int_member ("type"),
+                               idle_time = json_root.get_int_member ("idle_time"),
+                               time_since_active = json_root.get_int_member ("time_since_active"),
+                               time_correction = json_root.get_int_member ("time_correction")
                        };
                }
 
@@ -133,9 +133,9 @@ public class ActivityMonitor : Object {
        private UserActivity collect_activity () {
                UserActivity activity;
 
-               int sleep_time = backend.pop_sleep_time ();
-               int idle_time = backend.get_idle_seconds ();
-               int time_since_active = (int) (Util.get_real_time_seconds () - this.last_active_timestamp);
+               int64 sleep_time = backend.pop_sleep_time ();
+               int64 idle_time = backend.get_idle_seconds ();
+               int64 time_since_active = (int64) (Util.get_real_time_seconds () - 
this.last_active_timestamp);
 
                // Order is important here: some types of activity (or inactivity)
                // happen at the same time, and are only reported once.
@@ -148,7 +148,7 @@ public class ActivityMonitor : Object {
                                idle_time = 0,
                                time_correction = sleep_time
                        };
-                       GLib.debug ("Detected system sleep for %d seconds", sleep_time);
+                       GLib.debug ("Detected system sleep for " + int64.FORMAT + " seconds", sleep_time);
                } else if (this.session_status.is_locked ()) {
                        activity = UserActivity () {
                                type = ActivityType.LOCKED,
@@ -199,23 +199,24 @@ public abstract class ActivityMonitorBackend : Object {
                this.last_monotonic_time = json_root.get_int_member ("last_monotonic_time");
        }
 
-       protected abstract int time_since_last_event ();
+       protected abstract uint64 time_since_last_event_ms ();
 
-       public int get_idle_seconds () {
-               return this.time_since_last_event ();
+       public int64 get_idle_seconds () {
+               uint64 idle_ms = this.time_since_last_event_ms ();
+               return (int64) idle_ms / Util.MILLISECONDS_IN_SECONDS;
        }
 
        /** Detect if the device has been asleep using the difference between monotonic time and real time */
-       public int pop_sleep_time () {
-               int sleep_time;
+       public int64 pop_sleep_time () {
+               int64 sleep_time;
                int64 now_real = Util.get_real_time_seconds ();
                int64 now_monotonic = Util.get_monotonic_time_seconds ();
-               int real_time_delta = (int) (now_real - this.last_real_time);
-               int monotonic_time_delta = (int) (now_monotonic - this.last_monotonic_time).abs ();
+               int64 real_time_delta = (int64) (now_real - this.last_real_time);
+               int64 monotonic_time_delta = (int64) (now_monotonic - this.last_monotonic_time).abs ();
                
                if (this.last_real_time > 0 && this.last_monotonic_time > 0) {
                        if (real_time_delta > monotonic_time_delta) {
-                               sleep_time = (int) (real_time_delta - monotonic_time_delta);
+                               sleep_time = (int64) (real_time_delta - monotonic_time_delta);
                        } else {
                                sleep_time = real_time_delta;
                        }
diff --git a/helper/activity-monitor/MutterActivityMonitorBackend.vala 
b/helper/activity-monitor/MutterActivityMonitorBackend.vala
new file mode 100644
index 0000000..699174c
--- /dev/null
+++ b/helper/activity-monitor/MutterActivityMonitorBackend.vala
@@ -0,0 +1,108 @@
+/*
+ * This file is part of GNOME Break Timer.
+ *
+ * GNOME Break Timer 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 3 of the License, or
+ * (at your option) any later version.
+ *
+ * GNOME Break Timer 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 GNOME Break Timer.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+namespace BreakTimer.Helper {
+
+[DBus (name = "org.gnome.Mutter.IdleMonitor")]
+public interface IMutterIdleMonitor : Object {
+       public abstract uint32 add_idle_watch(uint64 interval_ms) throws GLib.DBusError, GLib.IOError;
+       public abstract uint32 add_user_active_watch() throws GLib.DBusError, GLib.IOError;
+       public abstract uint64 get_idletime() throws GLib.DBusError, GLib.IOError;
+       public abstract void remove_watch(uint32 id) throws GLib.DBusError, GLib.IOError;
+       public abstract void reset_idletime() throws GLib.DBusError, GLib.IOError;
+
+       public signal void watch_fired (uint32 id);
+}
+
+public class MutterActivityMonitorBackend : ActivityMonitorBackend {
+       private IMutterIdleMonitor? mutter_idle_monitor;
+       private uint32 idle_watch_id;
+       private uint32 user_active_watch_id;
+
+       private uint64 last_idle_time_ms;
+       private int64 last_idle_time_update_time_ms;
+       private bool user_is_active;
+
+       private static uint64 IDLE_WATCH_INTERVAL_MS = 1000;
+
+       public MutterActivityMonitorBackend () {
+               this.user_is_active = false;
+               Bus.watch_name (
+                       BusType.SESSION,
+                       "org.gnome.Mutter.IdleMonitor",
+                       BusNameWatcherFlags.NONE,
+                       this.mutter_idle_monitor_appeared,
+                       this.mutter_idle_monitor_disappeared
+               );
+       }
+
+       ~MutterActivityMonitorBackend() {
+               if (this.mutter_idle_monitor != null && this.idle_watch_id > 0) {
+                       this.mutter_idle_monitor.remove_watch (this.idle_watch_id);
+               }
+       }
+
+       private void mutter_idle_monitor_appeared () {
+               try {
+                       this.mutter_idle_monitor = Bus.get_proxy_sync (
+                               BusType.SESSION,
+                               "org.gnome.Mutter.IdleMonitor",
+                               "/org/gnome/Mutter/IdleMonitor/Core"
+                       );
+                       this.mutter_idle_monitor.watch_fired.connect 
(this.mutter_idle_monitor_watch_fired_cb);
+                       this.idle_watch_id = this.mutter_idle_monitor.add_idle_watch (IDLE_WATCH_INTERVAL_MS);
+                       this.update_last_idle_time();
+               } catch (IOError error) {
+                       this.mutter_idle_monitor = null;
+                       GLib.warning ("Error connecting to mutter idle monitor service: %s", error.message);
+               }
+       }
+
+       private void mutter_idle_monitor_disappeared () {
+               this.mutter_idle_monitor = null;
+               this.idle_watch_id = 0;
+       }
+
+       private void mutter_idle_monitor_watch_fired_cb (uint32 id) {
+               if (id == this.idle_watch_id) {
+                       this.user_is_active = false;
+                       this.update_last_idle_time();
+                       this.user_active_watch_id = this.mutter_idle_monitor.add_user_active_watch ();
+               } else if (id == this.user_active_watch_id) {
+                       this.user_is_active = true;
+                       this.user_active_watch_id = 0;
+               }
+       }
+
+       private void update_last_idle_time() {
+               this.last_idle_time_ms = this.mutter_idle_monitor.get_idletime ();
+               this.last_idle_time_update_time_ms = Util.get_monotonic_time_ms ();
+       }
+
+       protected override uint64 time_since_last_event_ms () {
+               if (this.user_is_active) {
+                       return 0;
+               } else {
+                       int64 now = Util.get_monotonic_time_ms ();
+                       int64 time_since = now - this.last_idle_time_update_time_ms;
+                       uint64 idle_time_ms = this.last_idle_time_ms + time_since;
+                       return idle_time_ms;
+               }
+       }
+}
+
+}
diff --git a/helper/break/TimerBreakController.vala b/helper/break/TimerBreakController.vala
index afb1c0a..faaab02 100644
--- a/helper/break/TimerBreakController.vala
+++ b/helper/break/TimerBreakController.vala
@@ -171,7 +171,8 @@ public abstract class TimerBreakController : BreakController {
                }
 
                if (activity.time_correction > 0) {
-                       this.duration_countdown.advance_time (activity.time_correction);
+                       // FIXME: Casting int64 to int
+                       this.duration_countdown.advance_time ((int) activity.time_correction);
                }
 
                if (this.state == State.WAITING) {
@@ -188,9 +189,9 @@ public abstract class TimerBreakController : BreakController {
                this.delayed_timer.freeze ();
                if (this.counting_timer.is_stopped ()) {
                        this.counting_timer.start_lap ();
-                       lap_time = activity.idle_time;
+                       lap_time = (int) activity.idle_time;
                } else {
-                       lap_time = (int)this.counting_timer.lap_time ();
+                       lap_time = (int) this.counting_timer.lap_time ();
                }
 
                this.counting (
diff --git a/helper/util/Util.vala b/helper/util/Util.vala
index 9addfe8..d9b38b3 100644
--- a/helper/util/Util.vala
+++ b/helper/util/Util.vala
@@ -37,6 +37,10 @@ public class Util {
                }
        }
 
+       public inline static int64 get_real_time_ms () {
+               return get_real_time () / MILLISECONDS_IN_SECONDS;
+       }
+
        public inline static int64 get_real_time_seconds () {
                return get_real_time () / MICROSECONDS_IN_SECONDS;
        }
@@ -49,6 +53,10 @@ public class Util {
                }
        }
 
+       public inline static int64 get_monotonic_time_ms () {
+               return get_monotonic_time () / MILLISECONDS_IN_SECONDS;
+       }
+
        public inline static int64 get_monotonic_time_seconds () {
                return get_monotonic_time () / MICROSECONDS_IN_SECONDS;
        }


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]