2
* Copyright 2013 Red Hat, Inc.
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.
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.
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/>.
17
* Adapted from gnome-session/gnome-session/gs-idle-monitor.c and
18
* from gnome-desktop/libgnome-desktop/gnome-idle-monitor.c
22
* SECTION:idle-monitor
23
* @title: MetaIdleMonitor
24
* @short_description: Mutter idle counter (similar to X's IDLETIME)
31
#include "meta-idle-monitor.h"
32
#include "meta-idle-monitor-xsync.h"
33
#include "meta-idle-monitor-dbus.h"
34
#include "meta-backend.h"
36
G_STATIC_ASSERT(sizeof(unsigned long) == sizeof(gpointer));
45
static GParamSpec *obj_props[PROP_LAST];
47
G_DEFINE_TYPE (MetaIdleMonitor, meta_idle_monitor, G_TYPE_OBJECT)
50
_meta_idle_monitor_watch_fire (MetaIdleMonitorWatch *watch)
52
MetaIdleMonitor *monitor;
54
gboolean is_user_active_watch;
56
monitor = watch->monitor;
57
g_object_ref (monitor);
59
if (watch->idle_source_id)
61
g_source_remove (watch->idle_source_id);
62
watch->idle_source_id = 0;
66
is_user_active_watch = (watch->timeout_msec == 0);
69
watch->callback (monitor, id, watch->user_data);
71
if (is_user_active_watch)
72
meta_idle_monitor_remove_watch (monitor, id);
74
g_object_unref (monitor);
78
meta_idle_monitor_dispose (GObject *object)
80
MetaIdleMonitor *monitor = META_IDLE_MONITOR (object);
82
g_clear_pointer (&monitor->watches, g_hash_table_destroy);
84
G_OBJECT_CLASS (meta_idle_monitor_parent_class)->dispose (object);
88
meta_idle_monitor_get_property (GObject *object,
93
MetaIdleMonitor *monitor = META_IDLE_MONITOR (object);
98
g_value_set_int (value, monitor->device_id);
101
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
107
meta_idle_monitor_set_property (GObject *object,
112
MetaIdleMonitor *monitor = META_IDLE_MONITOR (object);
116
monitor->device_id = g_value_get_int (value);
119
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
125
meta_idle_monitor_class_init (MetaIdleMonitorClass *klass)
127
GObjectClass *object_class = G_OBJECT_CLASS (klass);
129
object_class->dispose = meta_idle_monitor_dispose;
130
object_class->get_property = meta_idle_monitor_get_property;
131
object_class->set_property = meta_idle_monitor_set_property;
134
* MetaIdleMonitor:device_id:
136
* The device to listen to idletime on.
138
obj_props[PROP_DEVICE_ID] =
139
g_param_spec_int ("device-id",
141
"The device to listen to idletime on",
143
G_PARAM_STATIC_STRINGS | G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY);
144
g_object_class_install_property (object_class, PROP_DEVICE_ID, obj_props[PROP_DEVICE_ID]);
148
meta_idle_monitor_init (MetaIdleMonitor *monitor)
152
static MetaIdleMonitor *device_monitors[256];
155
* meta_idle_monitor_get_core:
157
* Returns: (transfer none): the #MetaIdleMonitor that tracks the server-global
158
* idletime for all devices. To track device-specific idletime,
159
* use meta_idle_monitor_get_for_device().
162
meta_idle_monitor_get_core (void)
164
MetaBackend *backend = meta_get_backend ();
165
return meta_backend_get_idle_monitor (backend, 0);
169
* meta_idle_monitor_get_for_device:
170
* @device_id: the device to get the idle time for.
172
* Returns: (transfer none): a new #MetaIdleMonitor that tracks the
173
* device-specific idletime for @device. To track server-global idletime
174
* for all devices, use meta_idle_monitor_get_core().
177
meta_idle_monitor_get_for_device (gint device_id)
179
MetaBackend *backend = meta_get_backend ();
180
return meta_backend_get_idle_monitor (backend, device_id);
183
static MetaIdleMonitorWatch *
184
make_watch (MetaIdleMonitor *monitor,
185
guint64 timeout_msec,
186
MetaIdleMonitorWatchFunc callback,
188
GDestroyNotify notify)
190
MetaIdleMonitorWatch *watch;
192
watch = META_IDLE_MONITOR_GET_CLASS (monitor)->make_watch (monitor,
198
g_hash_table_insert (monitor->watches,
199
GUINT_TO_POINTER (watch->id),
205
* meta_idle_monitor_add_idle_watch:
206
* @monitor: A #MetaIdleMonitor
207
* @interval_msec: The idletime interval, in milliseconds
208
* @callback: (nullable): The callback to call when the user has
209
* accumulated @interval_msec milliseconds of idle time.
210
* @user_data: (nullable): The user data to pass to the callback
211
* @notify: A #GDestroyNotify
213
* Returns: a watch id
215
* Adds a watch for a specific idle time. The callback will be called
216
* when the user has accumulated @interval_msec milliseconds of idle time.
217
* This function will return an ID that can either be passed to
218
* meta_idle_monitor_remove_watch(), or can be used to tell idle time
219
* watches apart if you have more than one.
221
* Also note that this function will only care about positive transitions
222
* (user's idle time exceeding a certain time). If you want to know about
223
* when the user has become active, use
224
* meta_idle_monitor_add_user_active_watch().
227
meta_idle_monitor_add_idle_watch (MetaIdleMonitor *monitor,
228
guint64 interval_msec,
229
MetaIdleMonitorWatchFunc callback,
231
GDestroyNotify notify)
233
MetaIdleMonitorWatch *watch;
235
g_return_val_if_fail (META_IS_IDLE_MONITOR (monitor), 0);
236
g_return_val_if_fail (interval_msec > 0, 0);
238
watch = make_watch (monitor,
248
* meta_idle_monitor_add_user_active_watch:
249
* @monitor: A #MetaIdleMonitor
250
* @callback: (nullable): The callback to call when the user is
252
* @user_data: (nullable): The user data to pass to the callback
253
* @notify: A #GDestroyNotify
255
* Returns: a watch id
257
* Add a one-time watch to know when the user is active again.
258
* Note that this watch is one-time and will de-activate after the
259
* function is called, for efficiency purposes. It's most convenient
260
* to call this when an idle watch, as added by
261
* meta_idle_monitor_add_idle_watch(), has triggered.
264
meta_idle_monitor_add_user_active_watch (MetaIdleMonitor *monitor,
265
MetaIdleMonitorWatchFunc callback,
267
GDestroyNotify notify)
269
MetaIdleMonitorWatch *watch;
271
g_return_val_if_fail (META_IS_IDLE_MONITOR (monitor), 0);
273
watch = make_watch (monitor,
283
* meta_idle_monitor_remove_watch:
284
* @monitor: A #MetaIdleMonitor
287
* Removes an idle time watcher, previously added by
288
* meta_idle_monitor_add_idle_watch() or
289
* meta_idle_monitor_add_user_active_watch().
292
meta_idle_monitor_remove_watch (MetaIdleMonitor *monitor,
295
g_return_if_fail (META_IS_IDLE_MONITOR (monitor));
297
g_object_ref (monitor);
298
g_hash_table_remove (monitor->watches,
299
GUINT_TO_POINTER (id));
300
g_object_unref (monitor);
304
* meta_idle_monitor_get_idletime:
305
* @monitor: A #MetaIdleMonitor
307
* Returns: The current idle time, in milliseconds, or -1 for not supported
310
meta_idle_monitor_get_idletime (MetaIdleMonitor *monitor)
312
return META_IDLE_MONITOR_GET_CLASS (monitor)->get_idletime (monitor);