1/* 2 * Copyright (c) 2016 gnome-pomodoro contributors 3 * 4 * This program is free software; you can redistribute it and/or modify 5 * it under the terms of the GNU General Public License as published by 6 * the Free Software Foundation, either version 3 of the License, or 7 * (at your option) any later version. 8 * 9 * This program is distributed in the hope that it will be useful, 10 * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 * GNU General Public License for more details. 13 * 14 * You should have received a copy of the GNU General Public License 15 * along with this program. If not, see <http://www.gnu.org/licenses/>. 16 * 17 * Authors: Kamil Prusko <kamilprusko@gmail.com> 18 * 19 */ 20 21using GLib; 22 23 24namespace GnomePlugin 25{ 26 /* Leas amount of time in seconds between detected events 27 * to say that user become active 28 */ 29 private const double IDLE_MONITOR_MIN_IDLE_TIME = 0.5; 30 31 private const string CURRENT_DESKTOP_VARIABLE = "XDG_CURRENT_DESKTOP"; 32 33 public class ApplicationExtension : Peas.ExtensionBase, Pomodoro.ApplicationExtension, GLib.AsyncInitable 34 { 35 private Pomodoro.Timer timer; 36 private GLib.Settings settings; 37 private Pomodoro.CapabilityGroup capabilities; 38 private GnomePlugin.GnomeShellExtension shell_extension; 39 private GnomePlugin.IdleMonitor idle_monitor; 40 private uint become_active_id = 0; 41 private bool can_enable = false; 42 private double last_activity_time = 0.0; 43 44 construct 45 { 46 this.settings = Pomodoro.get_settings ().get_child ("preferences"); 47 this.can_enable = GLib.Environment.get_variable (CURRENT_DESKTOP_VARIABLE) == "GNOME"; 48 49 // try { 50 // this.init_async.begin (GLib.Priority.DEFAULT, null); 51 // } 52 // catch (GLib.Error error) { 53 // warning ("Failed to initialize ApplicationExtension"); 54 // } 55 } 56 57 public async bool init_async (int io_priority = GLib.Priority.DEFAULT, 58 GLib.Cancellable? cancellable = null) 59 throws GLib.Error 60 { 61 var application = Pomodoro.Application.get_default (); 62 63 /* Mutter IdleMonitor */ 64 if (this.idle_monitor == null) { 65 this.capabilities = new Pomodoro.CapabilityGroup ("gnome"); 66 67 try { 68 this.idle_monitor = new GnomePlugin.IdleMonitor (); 69 70 this.timer = Pomodoro.Timer.get_default (); 71 this.timer.state_changed.connect_after (this.on_timer_state_changed); 72 73 this.capabilities.add (new Pomodoro.Capability ("idle-monitor")); 74 75 application.capabilities.add_group (this.capabilities, Pomodoro.Priority.HIGH); 76 } 77 catch (GLib.Error error) { 78 // Gnome.IdleMonitor not available 79 } 80 } 81 82 /* GNOME Shell extension */ 83 if (this.can_enable && this.shell_extension == null) { 84 this.shell_extension = new GnomePlugin.GnomeShellExtension (Config.EXTENSION_UUID, 85 Config.EXTENSION_DIR); 86 87 yield this.shell_extension.enable (cancellable); 88 } 89 90 return true; 91 } 92 93 ~ApplicationExtension () 94 { 95 this.timer.state_changed.disconnect (this.on_timer_state_changed); 96 97 if (this.become_active_id != 0) { 98 this.idle_monitor.remove_watch (this.become_active_id); 99 this.become_active_id = 0; 100 } 101 } 102 103 private void on_timer_state_changed (Pomodoro.TimerState state, 104 Pomodoro.TimerState previous_state) 105 { 106 if (this.become_active_id != 0) { 107 this.idle_monitor.remove_watch (this.become_active_id); 108 this.become_active_id = 0; 109 } 110 111 if (state is Pomodoro.PomodoroState && 112 previous_state is Pomodoro.BreakState && 113 previous_state.is_completed () && 114 this.settings.get_boolean ("pause-when-idle")) 115 { 116 this.become_active_id = this.idle_monitor.add_user_active_watch (this.on_become_active); 117 118 this.timer.pause (); 119 } 120 } 121 122 /** 123 * on_become_active callback 124 * 125 * We want to detect user/human activity so it sparse events. 126 */ 127 private void on_become_active (GnomePlugin.IdleMonitor monitor, 128 uint id) 129 { 130 var timestamp = Pomodoro.get_current_time (); 131 132 if (timestamp - this.last_activity_time < IDLE_MONITOR_MIN_IDLE_TIME) { 133 this.become_active_id = 0; 134 135 this.timer.resume (); 136 } 137 else { 138 this.become_active_id = this.idle_monitor.add_user_active_watch (this.on_become_active); 139 } 140 141 this.last_activity_time = timestamp; 142 } 143 } 144 145 public class PreferencesDialogExtension : Peas.ExtensionBase, Pomodoro.PreferencesDialogExtension 146 { 147 private Pomodoro.PreferencesDialog dialog; 148 149 private GLib.Settings settings; 150 private GLib.List<Gtk.ListBoxRow> rows; 151 152 construct 153 { 154 this.settings = new GLib.Settings ("org.gnome.pomodoro.plugins.gnome"); 155 this.dialog = Pomodoro.PreferencesDialog.get_default (); 156 157 this.setup_main_page (); 158 } 159 160 private void setup_main_page () 161 { 162 var main_page = this.dialog.get_page ("main") as Pomodoro.PreferencesMainPage; 163 164 var hide_system_notifications_toggle = new Gtk.Switch (); 165 hide_system_notifications_toggle.valign = Gtk.Align.CENTER; 166 167 var row = this.create_row (_("Hide other notifications"), 168 hide_system_notifications_toggle); 169 row.name = "hide-system-notifications"; 170 main_page.lisboxrow_sizegroup.add_widget (row); 171 main_page.desktop_listbox.add (row); 172 this.rows.prepend (row); 173 174 this.settings.bind ("hide-system-notifications", 175 hide_system_notifications_toggle, 176 "active", 177 GLib.SettingsBindFlags.DEFAULT); 178 } 179 180 ~PreferencesDialogExtension () 181 { 182 foreach (var row in this.rows) { 183 row.destroy (); 184 } 185 186 this.rows = null; 187 } 188 189 private Gtk.ListBoxRow create_row (string label, 190 Gtk.Widget widget) 191 { 192 var name_label = new Gtk.Label (label); 193 name_label.halign = Gtk.Align.START; 194 name_label.valign = Gtk.Align.BASELINE; 195 196 var box = new Gtk.Box (Gtk.Orientation.HORIZONTAL, 0); 197 box.pack_start (name_label, true, true, 0); 198 box.pack_start (widget, false, true, 0); 199 200 var row = new Gtk.ListBoxRow (); 201 row.activatable = false; 202 row.selectable = false; 203 row.add (box); 204 row.show_all (); 205 206 return row; 207 } 208 } 209} 210 211 212[ModuleInit] 213public void peas_register_types (GLib.TypeModule module) 214{ 215 var object_module = module as Peas.ObjectModule; 216 217 object_module.register_extension_type (typeof (Pomodoro.ApplicationExtension), 218 typeof (GnomePlugin.ApplicationExtension)); 219 220 object_module.register_extension_type (typeof (Pomodoro.PreferencesDialogExtension), 221 typeof (GnomePlugin.PreferencesDialogExtension)); 222} 223