~ubuntu-branches/ubuntu/oneiric/gnome-settings-daemon/oneiric

« back to all changes in this revision

Viewing changes to .pc/00git_numlock_status.patch/plugins/keyboard/gsd-keyboard-manager.c

  • Committer: Package Import Robot
  • Author(s): Rodrigo Moya
  • Date: 2011-09-19 17:05:48 UTC
  • mfrom: (1.1.51 upstream)
  • Revision ID: package-import@ubuntu.com-20110919170548-gegm8ewt6qf7v7lp
Tags: 3.1.92-0ubuntu1
* New upstream release
* debian/control:
  - Bump libcolord-dev build dependency
* debian/patches/00git_guard_against_division_by_0.patch:
* debian/patches/00git_dont_crash_if_session_not_ready.patch:
* debian/patches/00git_numlock_status.patch:
* debian/patches/00git_disconnect_callbacks.patch:
  - Remove upstream patches
* debian/patches/06_use_application_indicator.patch:
* debian/patches/16_use_synchronous_notifications.patch:
  - Rebased

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*-
2
 
 *
3
 
 * Copyright © 2001 Ximian, Inc.
4
 
 * Copyright (C) 2007 William Jon McCann <mccann@jhu.edu>
5
 
 *
6
 
 * This program is free software; you can redistribute it and/or modify
7
 
 * it under the terms of the GNU General Public License as published by
8
 
 * the Free Software Foundation; either version 2 of the License, or
9
 
 * (at your option) any later version.
10
 
 *
11
 
 * This program is distributed in the hope that it will be useful,
12
 
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13
 
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14
 
 * GNU 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, write to the Free Software
18
 
 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
19
 
 *
20
 
 */
21
 
 
22
 
#include "config.h"
23
 
 
24
 
#include <sys/types.h>
25
 
#include <sys/wait.h>
26
 
#include <stdlib.h>
27
 
#include <stdio.h>
28
 
#include <unistd.h>
29
 
#include <string.h>
30
 
#include <errno.h>
31
 
 
32
 
#include <locale.h>
33
 
 
34
 
#include <glib.h>
35
 
#include <glib/gi18n.h>
36
 
#include <gdk/gdk.h>
37
 
#include <gdk/gdkx.h>
38
 
#include <gtk/gtk.h>
39
 
 
40
 
#ifdef HAVE_X11_EXTENSIONS_XKB_H
41
 
#include <X11/XKBlib.h>
42
 
#include <X11/keysym.h>
43
 
#endif
44
 
 
45
 
#include "gnome-settings-profile.h"
46
 
#include "gsd-keyboard-manager.h"
47
 
#include "gsd-enums.h"
48
 
 
49
 
#include "gsd-keyboard-xkb.h"
50
 
 
51
 
#define GSD_KEYBOARD_MANAGER_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), GSD_TYPE_KEYBOARD_MANAGER, GsdKeyboardManagerPrivate))
52
 
 
53
 
#ifndef HOST_NAME_MAX
54
 
#  define HOST_NAME_MAX 255
55
 
#endif
56
 
 
57
 
#define GSD_KEYBOARD_DIR "org.gnome.settings-daemon.peripherals.keyboard"
58
 
 
59
 
#define KEY_REPEAT         "repeat"
60
 
#define KEY_CLICK          "click"
61
 
#define KEY_INTERVAL       "repeat-interval"
62
 
#define KEY_DELAY          "delay"
63
 
#define KEY_CLICK_VOLUME   "click-volume"
64
 
 
65
 
#define KEY_BELL_VOLUME    "bell-volume"
66
 
#define KEY_BELL_PITCH     "bell-pitch"
67
 
#define KEY_BELL_DURATION  "bell-duration"
68
 
#define KEY_BELL_MODE      "bell-mode"
69
 
 
70
 
struct GsdKeyboardManagerPrivate
71
 
{
72
 
        guint      start_idle_id;
73
 
        GSettings *settings;
74
 
        gboolean   have_xkb;
75
 
        gint       xkb_event_base;
76
 
};
77
 
 
78
 
static void     gsd_keyboard_manager_class_init  (GsdKeyboardManagerClass *klass);
79
 
static void     gsd_keyboard_manager_init        (GsdKeyboardManager      *keyboard_manager);
80
 
static void     gsd_keyboard_manager_finalize    (GObject                 *object);
81
 
 
82
 
G_DEFINE_TYPE (GsdKeyboardManager, gsd_keyboard_manager, G_TYPE_OBJECT)
83
 
 
84
 
static gpointer manager_object = NULL;
85
 
 
86
 
#ifdef HAVE_X11_EXTENSIONS_XKB_H
87
 
static gboolean
88
 
xkb_set_keyboard_autorepeat_rate (guint delay, guint interval)
89
 
{
90
 
        return XkbSetAutoRepeatRate (GDK_DISPLAY_XDISPLAY (gdk_display_get_default ()),
91
 
                                     XkbUseCoreKbd,
92
 
                                     delay,
93
 
                                     interval);
94
 
}
95
 
#endif
96
 
 
97
 
static char *
98
 
gsd_keyboard_get_hostname_key (void)
99
 
{
100
 
        /* FIXME disabled for now, as we need GSettingsList support:
101
 
         * https://bugzilla.gnome.org/show_bug.cgi?id=622126 */
102
 
#if 0
103
 
        const char *hostname;
104
 
 
105
 
        hostname = g_get_host_name ();
106
 
 
107
 
        if (g_str_equal (hostname, "localhost") == FALSE &&
108
 
            g_str_equal (hostname, "localhost.localdomain") == FALSE) {
109
 
                char *escaped;
110
 
                char *key;
111
 
 
112
 
                /* FIXME, really escape? */
113
 
                escaped = g_strdup (hostname);
114
 
                key = g_strdup_printf ("host-%s-0-numlock-on", escaped);
115
 
                g_free (escaped);
116
 
                return key;
117
 
        } else {
118
 
                g_message ("NumLock remembering disabled because hostname is set to \"localhost\"");
119
 
                return NULL;
120
 
        }
121
 
#endif
122
 
        return NULL;
123
 
}
124
 
 
125
 
#ifdef HAVE_X11_EXTENSIONS_XKB_H
126
 
 
127
 
typedef enum {
128
 
        NUMLOCK_STATE_OFF = 0,
129
 
        NUMLOCK_STATE_ON = 1,
130
 
        NUMLOCK_STATE_UNKNOWN = 2
131
 
} NumLockState;
132
 
 
133
 
static void
134
 
numlock_xkb_init (GsdKeyboardManager *manager)
135
 
{
136
 
        Display *dpy = GDK_DISPLAY_XDISPLAY (gdk_display_get_default ());
137
 
        gboolean have_xkb;
138
 
        int opcode, error_base, major, minor;
139
 
 
140
 
        have_xkb = XkbQueryExtension (dpy,
141
 
                                      &opcode,
142
 
                                      &manager->priv->xkb_event_base,
143
 
                                      &error_base,
144
 
                                      &major,
145
 
                                      &minor)
146
 
                && XkbUseExtension (dpy, &major, &minor);
147
 
 
148
 
        if (have_xkb) {
149
 
                XkbSelectEventDetails (dpy,
150
 
                                       XkbUseCoreKbd,
151
 
                                       XkbStateNotifyMask,
152
 
                                       XkbModifierLockMask,
153
 
                                       XkbModifierLockMask);
154
 
        } else {
155
 
                g_warning ("XKB extension not available");
156
 
        }
157
 
 
158
 
        manager->priv->have_xkb = have_xkb;
159
 
}
160
 
 
161
 
static unsigned
162
 
numlock_NumLock_modifier_mask (void)
163
 
{
164
 
        Display *dpy = GDK_DISPLAY_XDISPLAY (gdk_display_get_default ());
165
 
        return XkbKeysymToModifiers (dpy, XK_Num_Lock);
166
 
}
167
 
 
168
 
static void
169
 
numlock_set_xkb_state (NumLockState new_state)
170
 
{
171
 
        unsigned int num_mask;
172
 
        Display *dpy = GDK_DISPLAY_XDISPLAY (gdk_display_get_default ());
173
 
        if (new_state != NUMLOCK_STATE_ON && new_state != NUMLOCK_STATE_OFF)
174
 
                return;
175
 
        num_mask = numlock_NumLock_modifier_mask ();
176
 
        XkbLockModifiers (dpy, XkbUseCoreKbd, num_mask, new_state ? num_mask : 0);
177
 
}
178
 
 
179
 
static NumLockState
180
 
numlock_get_gsettings_state (GSettings *settings)
181
 
{
182
 
        int   curr_state;
183
 
        char *key;
184
 
 
185
 
        key = gsd_keyboard_get_hostname_key ();
186
 
        if (!key)
187
 
                return NUMLOCK_STATE_UNKNOWN;
188
 
 
189
 
        curr_state = g_settings_get_boolean (settings, key);
190
 
 
191
 
        g_free (key);
192
 
 
193
 
        return curr_state;
194
 
}
195
 
 
196
 
static void
197
 
numlock_set_gsettings_state (GSettings   *settings,
198
 
                             NumLockState new_state)
199
 
{
200
 
        char *key;
201
 
 
202
 
        if (new_state != NUMLOCK_STATE_ON && new_state != NUMLOCK_STATE_OFF) {
203
 
                return;
204
 
        }
205
 
 
206
 
        key = gsd_keyboard_get_hostname_key ();
207
 
        if (key) {
208
 
                g_settings_set_boolean (settings, key, new_state);
209
 
                g_free (key);
210
 
        }
211
 
}
212
 
 
213
 
static GdkFilterReturn
214
 
numlock_xkb_callback (GdkXEvent *xev_,
215
 
                      GdkEvent  *gdkev_,
216
 
                      gpointer   user_data)
217
 
{
218
 
        XEvent *xev = (XEvent *) xev_;
219
 
        GsdKeyboardManager *manager = (GsdKeyboardManager *) user_data;
220
 
 
221
 
        if (xev->type == manager->priv->xkb_event_base) {
222
 
                XkbEvent *xkbev = (XkbEvent *)xev;
223
 
                if (xkbev->any.xkb_type == XkbStateNotify)
224
 
                if (xkbev->state.changed & XkbModifierLockMask) {
225
 
                        unsigned num_mask = numlock_NumLock_modifier_mask ();
226
 
                        unsigned locked_mods = xkbev->state.locked_mods;
227
 
                        int numlock_state = !! (num_mask & locked_mods);
228
 
                        numlock_set_gsettings_state (manager->priv->settings, numlock_state);
229
 
                }
230
 
        }
231
 
        return GDK_FILTER_CONTINUE;
232
 
}
233
 
 
234
 
static void
235
 
numlock_install_xkb_callback (GsdKeyboardManager *manager)
236
 
{
237
 
        if (!manager->priv->have_xkb)
238
 
                return;
239
 
 
240
 
        gdk_window_add_filter (NULL,
241
 
                               numlock_xkb_callback,
242
 
                               manager);
243
 
}
244
 
 
245
 
#endif /* HAVE_X11_EXTENSIONS_XKB_H */
246
 
 
247
 
static guint
248
 
_gsd_settings_get_uint (GSettings  *settings,
249
 
                        const char *key)
250
 
{
251
 
        guint value;
252
 
 
253
 
        g_settings_get (settings, key, "u", &value);
254
 
        return value;
255
 
}
256
 
 
257
 
static void
258
 
apply_settings (GSettings          *settings,
259
 
                const char         *key,
260
 
                GsdKeyboardManager *manager)
261
 
{
262
 
        XKeyboardControl kbdcontrol;
263
 
        gboolean         repeat;
264
 
        gboolean         click;
265
 
        guint            interval;
266
 
        guint            delay;
267
 
        int              click_volume;
268
 
        int              bell_volume;
269
 
        int              bell_pitch;
270
 
        int              bell_duration;
271
 
        GsdBellMode      bell_mode;
272
 
#ifdef HAVE_X11_EXTENSIONS_XKB_H
273
 
        gboolean         rnumlock;
274
 
#endif /* HAVE_X11_EXTENSIONS_XKB_H */
275
 
 
276
 
        repeat        = g_settings_get_boolean  (settings, KEY_REPEAT);
277
 
        click         = g_settings_get_boolean  (settings, KEY_CLICK);
278
 
        interval      = _gsd_settings_get_uint  (settings, KEY_INTERVAL);
279
 
        delay         = _gsd_settings_get_uint  (settings, KEY_DELAY);
280
 
        click_volume  = g_settings_get_int   (settings, KEY_CLICK_VOLUME);
281
 
        bell_pitch    = g_settings_get_int   (settings, KEY_BELL_PITCH);
282
 
        bell_duration = g_settings_get_int   (settings, KEY_BELL_DURATION);
283
 
 
284
 
        bell_mode = g_settings_get_enum (settings, KEY_BELL_MODE);
285
 
        bell_volume   = (bell_mode == GSD_BELL_MODE_ON) ? 50 : 0;
286
 
 
287
 
#ifdef HAVE_X11_EXTENSIONS_XKB_H
288
 
        rnumlock      = g_settings_get_boolean  (settings, "remember-numlock-state");
289
 
#endif /* HAVE_X11_EXTENSIONS_XKB_H */
290
 
 
291
 
        gdk_error_trap_push ();
292
 
        if (repeat) {
293
 
                gboolean rate_set = FALSE;
294
 
 
295
 
                XAutoRepeatOn (GDK_DISPLAY_XDISPLAY (gdk_display_get_default ()));
296
 
                /* Use XKB in preference */
297
 
#ifdef HAVE_X11_EXTENSIONS_XKB_H
298
 
                rate_set = xkb_set_keyboard_autorepeat_rate (delay, interval);
299
 
#endif
300
 
                if (!rate_set)
301
 
                        g_warning ("Neither XKeyboard not Xfree86's keyboard extensions are available,\n"
302
 
                                   "no way to support keyboard autorepeat rate settings");
303
 
        } else {
304
 
                XAutoRepeatOff (GDK_DISPLAY_XDISPLAY (gdk_display_get_default ()));
305
 
        }
306
 
 
307
 
        /* as percentage from 0..100 inclusive */
308
 
        if (click_volume < 0) {
309
 
                click_volume = 0;
310
 
        } else if (click_volume > 100) {
311
 
                click_volume = 100;
312
 
        }
313
 
        kbdcontrol.key_click_percent = click ? click_volume : 0;
314
 
        kbdcontrol.bell_percent = bell_volume;
315
 
        kbdcontrol.bell_pitch = bell_pitch;
316
 
        kbdcontrol.bell_duration = bell_duration;
317
 
        XChangeKeyboardControl (GDK_DISPLAY_XDISPLAY (gdk_display_get_default ()),
318
 
                                KBKeyClickPercent | KBBellPercent | KBBellPitch | KBBellDuration,
319
 
                                &kbdcontrol);
320
 
 
321
 
#ifdef HAVE_X11_EXTENSIONS_XKB_H
322
 
        if (manager->priv->have_xkb && rnumlock) {
323
 
                numlock_set_xkb_state (numlock_get_gsettings_state (manager->priv->settings));
324
 
        }
325
 
#endif /* HAVE_X11_EXTENSIONS_XKB_H */
326
 
 
327
 
        XSync (GDK_DISPLAY_XDISPLAY (gdk_display_get_default ()), FALSE);
328
 
        gdk_error_trap_pop_ignored ();
329
 
}
330
 
 
331
 
void
332
 
gsd_keyboard_manager_apply_settings (GsdKeyboardManager *manager)
333
 
{
334
 
        apply_settings (manager->priv->settings, NULL, manager);
335
 
}
336
 
 
337
 
static gboolean
338
 
start_keyboard_idle_cb (GsdKeyboardManager *manager)
339
 
{
340
 
        gnome_settings_profile_start (NULL);
341
 
 
342
 
        g_debug ("Starting keyboard manager");
343
 
 
344
 
        manager->priv->have_xkb = 0;
345
 
        manager->priv->settings = g_settings_new (GSD_KEYBOARD_DIR);
346
 
 
347
 
        /* Essential - xkb initialization should happen before */
348
 
        gsd_keyboard_xkb_init (manager);
349
 
 
350
 
#ifdef HAVE_X11_EXTENSIONS_XKB_H
351
 
        numlock_xkb_init (manager);
352
 
#endif /* HAVE_X11_EXTENSIONS_XKB_H */
353
 
 
354
 
        /* apply current settings before we install the callback */
355
 
        gsd_keyboard_manager_apply_settings (manager);
356
 
 
357
 
        g_signal_connect (G_OBJECT (manager->priv->settings), "changed",
358
 
                          G_CALLBACK (apply_settings), manager);
359
 
 
360
 
#ifdef HAVE_X11_EXTENSIONS_XKB_H
361
 
        numlock_install_xkb_callback (manager);
362
 
#endif /* HAVE_X11_EXTENSIONS_XKB_H */
363
 
 
364
 
        gnome_settings_profile_end (NULL);
365
 
 
366
 
        manager->priv->start_idle_id = 0;
367
 
 
368
 
        return FALSE;
369
 
}
370
 
 
371
 
gboolean
372
 
gsd_keyboard_manager_start (GsdKeyboardManager *manager,
373
 
                            GError            **error)
374
 
{
375
 
        gnome_settings_profile_start (NULL);
376
 
 
377
 
        manager->priv->start_idle_id = g_idle_add ((GSourceFunc) start_keyboard_idle_cb, manager);
378
 
 
379
 
        gnome_settings_profile_end (NULL);
380
 
 
381
 
        return TRUE;
382
 
}
383
 
 
384
 
void
385
 
gsd_keyboard_manager_stop (GsdKeyboardManager *manager)
386
 
{
387
 
        GsdKeyboardManagerPrivate *p = manager->priv;
388
 
 
389
 
        g_debug ("Stopping keyboard manager");
390
 
 
391
 
        if (p->settings != NULL) {
392
 
                g_object_unref (p->settings);
393
 
                p->settings = NULL;
394
 
        }
395
 
 
396
 
#if HAVE_X11_EXTENSIONS_XKB_H
397
 
        if (p->have_xkb) {
398
 
                gdk_window_remove_filter (NULL,
399
 
                                          numlock_xkb_callback,
400
 
                                          manager);
401
 
        }
402
 
#endif /* HAVE_X11_EXTENSIONS_XKB_H */
403
 
 
404
 
        gsd_keyboard_xkb_shutdown ();
405
 
}
406
 
 
407
 
static void
408
 
gsd_keyboard_manager_set_property (GObject        *object,
409
 
                                   guint           prop_id,
410
 
                                   const GValue   *value,
411
 
                                   GParamSpec     *pspec)
412
 
{
413
 
        switch (prop_id) {
414
 
        default:
415
 
                G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
416
 
                break;
417
 
        }
418
 
}
419
 
 
420
 
static void
421
 
gsd_keyboard_manager_get_property (GObject        *object,
422
 
                                   guint           prop_id,
423
 
                                   GValue         *value,
424
 
                                   GParamSpec     *pspec)
425
 
{
426
 
        switch (prop_id) {
427
 
        default:
428
 
                G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
429
 
                break;
430
 
        }
431
 
}
432
 
 
433
 
static GObject *
434
 
gsd_keyboard_manager_constructor (GType                  type,
435
 
                                  guint                  n_construct_properties,
436
 
                                  GObjectConstructParam *construct_properties)
437
 
{
438
 
        GsdKeyboardManager      *keyboard_manager;
439
 
 
440
 
        keyboard_manager = GSD_KEYBOARD_MANAGER (G_OBJECT_CLASS (gsd_keyboard_manager_parent_class)->constructor (type,
441
 
                                                                                                      n_construct_properties,
442
 
                                                                                                      construct_properties));
443
 
 
444
 
        return G_OBJECT (keyboard_manager);
445
 
}
446
 
 
447
 
static void
448
 
gsd_keyboard_manager_dispose (GObject *object)
449
 
{
450
 
        G_OBJECT_CLASS (gsd_keyboard_manager_parent_class)->dispose (object);
451
 
}
452
 
 
453
 
static void
454
 
gsd_keyboard_manager_class_init (GsdKeyboardManagerClass *klass)
455
 
{
456
 
        GObjectClass   *object_class = G_OBJECT_CLASS (klass);
457
 
 
458
 
        object_class->get_property = gsd_keyboard_manager_get_property;
459
 
        object_class->set_property = gsd_keyboard_manager_set_property;
460
 
        object_class->constructor = gsd_keyboard_manager_constructor;
461
 
        object_class->dispose = gsd_keyboard_manager_dispose;
462
 
        object_class->finalize = gsd_keyboard_manager_finalize;
463
 
 
464
 
        g_type_class_add_private (klass, sizeof (GsdKeyboardManagerPrivate));
465
 
}
466
 
 
467
 
static void
468
 
gsd_keyboard_manager_init (GsdKeyboardManager *manager)
469
 
{
470
 
        manager->priv = GSD_KEYBOARD_MANAGER_GET_PRIVATE (manager);
471
 
}
472
 
 
473
 
static void
474
 
gsd_keyboard_manager_finalize (GObject *object)
475
 
{
476
 
        GsdKeyboardManager *keyboard_manager;
477
 
 
478
 
        g_return_if_fail (object != NULL);
479
 
        g_return_if_fail (GSD_IS_KEYBOARD_MANAGER (object));
480
 
 
481
 
        keyboard_manager = GSD_KEYBOARD_MANAGER (object);
482
 
 
483
 
        g_return_if_fail (keyboard_manager->priv != NULL);
484
 
 
485
 
        if (keyboard_manager->priv->start_idle_id != 0)
486
 
                g_source_remove (keyboard_manager->priv->start_idle_id);
487
 
 
488
 
        G_OBJECT_CLASS (gsd_keyboard_manager_parent_class)->finalize (object);
489
 
}
490
 
 
491
 
GsdKeyboardManager *
492
 
gsd_keyboard_manager_new (void)
493
 
{
494
 
        if (manager_object != NULL) {
495
 
                g_object_ref (manager_object);
496
 
        } else {
497
 
                manager_object = g_object_new (GSD_TYPE_KEYBOARD_MANAGER, NULL);
498
 
                g_object_add_weak_pointer (manager_object,
499
 
                                           (gpointer *) &manager_object);
500
 
        }
501
 
 
502
 
        return GSD_KEYBOARD_MANAGER (manager_object);
503
 
}