1
/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
4
* Copyright 2013 Red Hat, Inc.
6
* This program is free software; you can redistribute it and/or
7
* modify it under the terms of the GNU General Public License as
8
* published by the Free Software Foundation; either version 2 of the
9
* License, or (at your option) any later version.
11
* This program is distributed in the hope that it will be useful, but
12
* WITHOUT ANY WARRANTY; without even the implied warranty of
13
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14
* General Public License for more details.
16
* You should have received a copy of the GNU General Public License
17
* along with this program; if not, see <http://www.gnu.org/licenses/>.
19
* Adapted from gnome-session/gnome-session/gs-idle-monitor.c and
20
* from gnome-desktop/libgnome-desktop/gnome-idle-monitor.c
24
* SECTION:idle-monitor
25
* @title: MetaIdleMonitor
26
* @short_description: Mutter idle counter (similar to X's IDLETIME)
32
#include <clutter/clutter.h>
34
#include <X11/extensions/sync.h>
36
#include <meta/util.h>
37
#include <meta/main.h>
38
#include <meta/meta-idle-monitor.h>
39
#include "meta-idle-monitor-private.h"
40
#include "meta-idle-monitor-dbus.h"
41
#include "meta-backend-private.h"
43
G_STATIC_ASSERT(sizeof(unsigned long) == sizeof(gpointer));
52
static GParamSpec *obj_props[PROP_LAST];
54
G_DEFINE_TYPE (MetaIdleMonitor, meta_idle_monitor, G_TYPE_OBJECT)
57
_meta_idle_monitor_watch_fire (MetaIdleMonitorWatch *watch)
59
MetaIdleMonitor *monitor;
61
gboolean is_user_active_watch;
63
monitor = watch->monitor;
64
g_object_ref (monitor);
66
if (watch->idle_source_id)
68
g_source_remove (watch->idle_source_id);
69
watch->idle_source_id = 0;
73
is_user_active_watch = (watch->timeout_msec == 0);
76
watch->callback (monitor, id, watch->user_data);
78
if (is_user_active_watch)
79
meta_idle_monitor_remove_watch (monitor, id);
81
g_object_unref (monitor);
85
meta_idle_monitor_dispose (GObject *object)
87
MetaIdleMonitor *monitor = META_IDLE_MONITOR (object);
89
g_clear_pointer (&monitor->watches, g_hash_table_destroy);
91
G_OBJECT_CLASS (meta_idle_monitor_parent_class)->dispose (object);
95
meta_idle_monitor_get_property (GObject *object,
100
MetaIdleMonitor *monitor = META_IDLE_MONITOR (object);
105
g_value_set_int (value, monitor->device_id);
108
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
114
meta_idle_monitor_set_property (GObject *object,
119
MetaIdleMonitor *monitor = META_IDLE_MONITOR (object);
123
monitor->device_id = g_value_get_int (value);
126
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
132
meta_idle_monitor_class_init (MetaIdleMonitorClass *klass)
134
GObjectClass *object_class = G_OBJECT_CLASS (klass);
136
object_class->dispose = meta_idle_monitor_dispose;
137
object_class->get_property = meta_idle_monitor_get_property;
138
object_class->set_property = meta_idle_monitor_set_property;
141
* MetaIdleMonitor:device_id:
143
* The device to listen to idletime on.
145
obj_props[PROP_DEVICE_ID] =
146
g_param_spec_int ("device-id",
148
"The device to listen to idletime on",
150
G_PARAM_STATIC_STRINGS | G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY);
151
g_object_class_install_property (object_class, PROP_DEVICE_ID, obj_props[PROP_DEVICE_ID]);
155
meta_idle_monitor_init (MetaIdleMonitor *monitor)
160
* meta_idle_monitor_get_core:
162
* Returns: (transfer none): the #MetaIdleMonitor that tracks the server-global
163
* idletime for all devices. To track device-specific idletime,
164
* use meta_idle_monitor_get_for_device().
167
meta_idle_monitor_get_core (void)
169
MetaBackend *backend = meta_get_backend ();
170
return meta_backend_get_idle_monitor (backend, 0);
174
* meta_idle_monitor_get_for_device:
175
* @device_id: the device to get the idle time for.
177
* Returns: (transfer none): a new #MetaIdleMonitor that tracks the
178
* device-specific idletime for @device. To track server-global idletime
179
* for all devices, use meta_idle_monitor_get_core().
182
meta_idle_monitor_get_for_device (int device_id)
184
MetaBackend *backend = meta_get_backend ();
185
return meta_backend_get_idle_monitor (backend, device_id);
188
static MetaIdleMonitorWatch *
189
make_watch (MetaIdleMonitor *monitor,
190
guint64 timeout_msec,
191
MetaIdleMonitorWatchFunc callback,
193
GDestroyNotify notify)
195
MetaIdleMonitorWatch *watch;
197
watch = META_IDLE_MONITOR_GET_CLASS (monitor)->make_watch (monitor,
203
g_hash_table_insert (monitor->watches,
204
GUINT_TO_POINTER (watch->id),
210
* meta_idle_monitor_add_idle_watch:
211
* @monitor: A #MetaIdleMonitor
212
* @interval_msec: The idletime interval, in milliseconds
213
* @callback: (nullable): The callback to call when the user has
214
* accumulated @interval_msec milliseconds of idle time.
215
* @user_data: (nullable): The user data to pass to the callback
216
* @notify: A #GDestroyNotify
218
* Returns: a watch id
220
* Adds a watch for a specific idle time. The callback will be called
221
* when the user has accumulated @interval_msec milliseconds of idle time.
222
* This function will return an ID that can either be passed to
223
* meta_idle_monitor_remove_watch(), or can be used to tell idle time
224
* watches apart if you have more than one.
226
* Also note that this function will only care about positive transitions
227
* (user's idle time exceeding a certain time). If you want to know about
228
* when the user has become active, use
229
* meta_idle_monitor_add_user_active_watch().
232
meta_idle_monitor_add_idle_watch (MetaIdleMonitor *monitor,
233
guint64 interval_msec,
234
MetaIdleMonitorWatchFunc callback,
236
GDestroyNotify notify)
238
MetaIdleMonitorWatch *watch;
240
g_return_val_if_fail (META_IS_IDLE_MONITOR (monitor), 0);
241
g_return_val_if_fail (interval_msec > 0, 0);
243
watch = make_watch (monitor,
253
* meta_idle_monitor_add_user_active_watch:
254
* @monitor: A #MetaIdleMonitor
255
* @callback: (nullable): The callback to call when the user is
257
* @user_data: (nullable): The user data to pass to the callback
258
* @notify: A #GDestroyNotify
260
* Returns: a watch id
262
* Add a one-time watch to know when the user is active again.
263
* Note that this watch is one-time and will de-activate after the
264
* function is called, for efficiency purposes. It's most convenient
265
* to call this when an idle watch, as added by
266
* meta_idle_monitor_add_idle_watch(), has triggered.
269
meta_idle_monitor_add_user_active_watch (MetaIdleMonitor *monitor,
270
MetaIdleMonitorWatchFunc callback,
272
GDestroyNotify notify)
274
MetaIdleMonitorWatch *watch;
276
g_return_val_if_fail (META_IS_IDLE_MONITOR (monitor), 0);
278
watch = make_watch (monitor,
288
* meta_idle_monitor_remove_watch:
289
* @monitor: A #MetaIdleMonitor
292
* Removes an idle time watcher, previously added by
293
* meta_idle_monitor_add_idle_watch() or
294
* meta_idle_monitor_add_user_active_watch().
297
meta_idle_monitor_remove_watch (MetaIdleMonitor *monitor,
300
g_return_if_fail (META_IS_IDLE_MONITOR (monitor));
302
g_object_ref (monitor);
303
g_hash_table_remove (monitor->watches,
304
GUINT_TO_POINTER (id));
305
g_object_unref (monitor);
309
* meta_idle_monitor_get_idletime:
310
* @monitor: A #MetaIdleMonitor
312
* Returns: The current idle time, in milliseconds, or -1 for not supported
315
meta_idle_monitor_get_idletime (MetaIdleMonitor *monitor)
317
return META_IDLE_MONITOR_GET_CLASS (monitor)->get_idletime (monitor);