~elementary-os/ubuntu-package-imports/mutter-bionic

« back to all changes in this revision

Viewing changes to src/backends/meta-idle-monitor.c

  • Committer: RabbitBot
  • Date: 2018-04-11 14:49:36 UTC
  • Revision ID: rabbitbot@elementary.io-20180411144936-hgymqa9d8d1xfpbh
Initial import, version 3.28.0-2

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
 
2
 
 
3
/*
 
4
 * Copyright 2013 Red Hat, Inc.
 
5
 *
 
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.
 
10
 *
 
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.
 
15
 *
 
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/>.
 
18
 *
 
19
 * Adapted from gnome-session/gnome-session/gs-idle-monitor.c and
 
20
 *         from gnome-desktop/libgnome-desktop/gnome-idle-monitor.c
 
21
 */
 
22
 
 
23
/**
 
24
 * SECTION:idle-monitor
 
25
 * @title: MetaIdleMonitor
 
26
 * @short_description: Mutter idle counter (similar to X's IDLETIME)
 
27
 */
 
28
 
 
29
#include "config.h"
 
30
 
 
31
#include <string.h>
 
32
#include <clutter/clutter.h>
 
33
#include <X11/Xlib.h>
 
34
#include <X11/extensions/sync.h>
 
35
 
 
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"
 
42
 
 
43
G_STATIC_ASSERT(sizeof(unsigned long) == sizeof(gpointer));
 
44
 
 
45
enum
 
46
{
 
47
  PROP_0,
 
48
  PROP_DEVICE_ID,
 
49
  PROP_LAST,
 
50
};
 
51
 
 
52
static GParamSpec *obj_props[PROP_LAST];
 
53
 
 
54
G_DEFINE_TYPE (MetaIdleMonitor, meta_idle_monitor, G_TYPE_OBJECT)
 
55
 
 
56
void
 
57
_meta_idle_monitor_watch_fire (MetaIdleMonitorWatch *watch)
 
58
{
 
59
  MetaIdleMonitor *monitor;
 
60
  guint id;
 
61
  gboolean is_user_active_watch;
 
62
 
 
63
  monitor = watch->monitor;
 
64
  g_object_ref (monitor);
 
65
 
 
66
  if (watch->idle_source_id)
 
67
    {
 
68
      g_source_remove (watch->idle_source_id);
 
69
      watch->idle_source_id = 0;
 
70
    }
 
71
 
 
72
  id = watch->id;
 
73
  is_user_active_watch = (watch->timeout_msec == 0);
 
74
 
 
75
  if (watch->callback)
 
76
    watch->callback (monitor, id, watch->user_data);
 
77
 
 
78
  if (is_user_active_watch)
 
79
    meta_idle_monitor_remove_watch (monitor, id);
 
80
 
 
81
  g_object_unref (monitor);
 
82
}
 
83
 
 
84
static void
 
85
meta_idle_monitor_dispose (GObject *object)
 
86
{
 
87
  MetaIdleMonitor *monitor = META_IDLE_MONITOR (object);
 
88
 
 
89
  g_clear_pointer (&monitor->watches, g_hash_table_destroy);
 
90
 
 
91
  G_OBJECT_CLASS (meta_idle_monitor_parent_class)->dispose (object);
 
92
}
 
93
 
 
94
static void
 
95
meta_idle_monitor_get_property (GObject    *object,
 
96
                                guint       prop_id,
 
97
                                GValue     *value,
 
98
                                GParamSpec *pspec)
 
99
{
 
100
  MetaIdleMonitor *monitor = META_IDLE_MONITOR (object);
 
101
 
 
102
  switch (prop_id)
 
103
    {
 
104
    case PROP_DEVICE_ID:
 
105
      g_value_set_int (value, monitor->device_id);
 
106
      break;
 
107
    default:
 
108
      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
 
109
      break;
 
110
    }
 
111
}
 
112
 
 
113
static void
 
114
meta_idle_monitor_set_property (GObject      *object,
 
115
                                guint         prop_id,
 
116
                                const GValue *value,
 
117
                                GParamSpec   *pspec)
 
118
{
 
119
  MetaIdleMonitor *monitor = META_IDLE_MONITOR (object);
 
120
  switch (prop_id)
 
121
    {
 
122
    case PROP_DEVICE_ID:
 
123
      monitor->device_id = g_value_get_int (value);
 
124
      break;
 
125
    default:
 
126
      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
 
127
      break;
 
128
    }
 
129
}
 
130
 
 
131
static void
 
132
meta_idle_monitor_class_init (MetaIdleMonitorClass *klass)
 
133
{
 
134
  GObjectClass *object_class = G_OBJECT_CLASS (klass);
 
135
 
 
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;
 
139
 
 
140
  /**
 
141
   * MetaIdleMonitor:device_id:
 
142
   *
 
143
   * The device to listen to idletime on.
 
144
   */
 
145
  obj_props[PROP_DEVICE_ID] =
 
146
    g_param_spec_int ("device-id",
 
147
                      "Device ID",
 
148
                      "The device to listen to idletime on",
 
149
                      0, 255, 0,
 
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]);
 
152
}
 
153
 
 
154
static void
 
155
meta_idle_monitor_init (MetaIdleMonitor *monitor)
 
156
{
 
157
}
 
158
 
 
159
/**
 
160
 * meta_idle_monitor_get_core:
 
161
 *
 
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().
 
165
 */
 
166
MetaIdleMonitor *
 
167
meta_idle_monitor_get_core (void)
 
168
{
 
169
  MetaBackend *backend = meta_get_backend ();
 
170
  return meta_backend_get_idle_monitor (backend, 0);
 
171
}
 
172
 
 
173
/**
 
174
 * meta_idle_monitor_get_for_device:
 
175
 * @device_id: the device to get the idle time for.
 
176
 *
 
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().
 
180
 */
 
181
MetaIdleMonitor *
 
182
meta_idle_monitor_get_for_device (int device_id)
 
183
{
 
184
  MetaBackend *backend = meta_get_backend ();
 
185
  return meta_backend_get_idle_monitor (backend, device_id);
 
186
}
 
187
 
 
188
static MetaIdleMonitorWatch *
 
189
make_watch (MetaIdleMonitor           *monitor,
 
190
            guint64                    timeout_msec,
 
191
            MetaIdleMonitorWatchFunc   callback,
 
192
            gpointer                   user_data,
 
193
            GDestroyNotify             notify)
 
194
{
 
195
  MetaIdleMonitorWatch *watch;
 
196
 
 
197
  watch = META_IDLE_MONITOR_GET_CLASS (monitor)->make_watch (monitor,
 
198
                                                             timeout_msec,
 
199
                                                             callback,
 
200
                                                             user_data,
 
201
                                                             notify);
 
202
 
 
203
  g_hash_table_insert (monitor->watches,
 
204
                       GUINT_TO_POINTER (watch->id),
 
205
                       watch);
 
206
  return watch;
 
207
}
 
208
 
 
209
/**
 
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
 
217
 *
 
218
 * Returns: a watch id
 
219
 *
 
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.
 
225
 *
 
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().
 
230
 */
 
231
guint
 
232
meta_idle_monitor_add_idle_watch (MetaIdleMonitor              *monitor,
 
233
                                  guint64                       interval_msec,
 
234
                                  MetaIdleMonitorWatchFunc      callback,
 
235
                                  gpointer                      user_data,
 
236
                                  GDestroyNotify                notify)
 
237
{
 
238
  MetaIdleMonitorWatch *watch;
 
239
 
 
240
  g_return_val_if_fail (META_IS_IDLE_MONITOR (monitor), 0);
 
241
  g_return_val_if_fail (interval_msec > 0, 0);
 
242
 
 
243
  watch = make_watch (monitor,
 
244
                      interval_msec,
 
245
                      callback,
 
246
                      user_data,
 
247
                      notify);
 
248
 
 
249
  return watch->id;
 
250
}
 
251
 
 
252
/**
 
253
 * meta_idle_monitor_add_user_active_watch:
 
254
 * @monitor: A #MetaIdleMonitor
 
255
 * @callback: (nullable): The callback to call when the user is
 
256
 *     active again.
 
257
 * @user_data: (nullable): The user data to pass to the callback
 
258
 * @notify: A #GDestroyNotify
 
259
 *
 
260
 * Returns: a watch id
 
261
 *
 
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.
 
267
 */
 
268
guint
 
269
meta_idle_monitor_add_user_active_watch (MetaIdleMonitor          *monitor,
 
270
                                         MetaIdleMonitorWatchFunc  callback,
 
271
                                         gpointer                  user_data,
 
272
                                         GDestroyNotify            notify)
 
273
{
 
274
  MetaIdleMonitorWatch *watch;
 
275
 
 
276
  g_return_val_if_fail (META_IS_IDLE_MONITOR (monitor), 0);
 
277
 
 
278
  watch = make_watch (monitor,
 
279
                      0,
 
280
                      callback,
 
281
                      user_data,
 
282
                      notify);
 
283
 
 
284
  return watch->id;
 
285
}
 
286
 
 
287
/**
 
288
 * meta_idle_monitor_remove_watch:
 
289
 * @monitor: A #MetaIdleMonitor
 
290
 * @id: A watch ID
 
291
 *
 
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().
 
295
 */
 
296
void
 
297
meta_idle_monitor_remove_watch (MetaIdleMonitor *monitor,
 
298
                                guint            id)
 
299
{
 
300
  g_return_if_fail (META_IS_IDLE_MONITOR (monitor));
 
301
 
 
302
  g_object_ref (monitor);
 
303
  g_hash_table_remove (monitor->watches,
 
304
                       GUINT_TO_POINTER (id));
 
305
  g_object_unref (monitor);
 
306
}
 
307
 
 
308
/**
 
309
 * meta_idle_monitor_get_idletime:
 
310
 * @monitor: A #MetaIdleMonitor
 
311
 *
 
312
 * Returns: The current idle time, in milliseconds, or -1 for not supported
 
313
 */
 
314
gint64
 
315
meta_idle_monitor_get_idletime (MetaIdleMonitor *monitor)
 
316
{
 
317
  return META_IDLE_MONITOR_GET_CLASS (monitor)->get_idletime (monitor);
 
318
}