~ubuntu-branches/ubuntu/trusty/unity-control-center/trusty

« back to all changes in this revision

Viewing changes to panels/mouse/gnome-mouse-properties.c

  • Committer: Package Import Robot
  • Author(s): Robert Ancell
  • Date: 2014-01-08 16:29:18 UTC
  • Revision ID: package-import@ubuntu.com-20140108162918-g29dd08tr913y2qh
Tags: upstream-14.04.0
ImportĀ upstreamĀ versionĀ 14.04.0

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*-
 
2
 *
 
3
 * Copyright (C) 2001, 2012 Red Hat, Inc.
 
4
 * Copyright (C) 2001 Ximian, Inc.
 
5
 *
 
6
 * Written by: Jonathon Blandford <jrb@redhat.com>,
 
7
 *             Bradford Hovinen <hovinen@ximian.com>,
 
8
 *             Ondrej Holy <oholy@redhat.com>,
 
9
 *
 
10
 * This program is free software; you can redistribute it and/or modify
 
11
 * it under the terms of the GNU General Public License as published by
 
12
 * the Free Software Foundation; either version 2, or (at your option)
 
13
 * any later version.
 
14
 *
 
15
 * This program is distributed in the hope that it will be useful,
 
16
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 
17
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 
18
 * GNU General Public License for more details.
 
19
 *
 
20
 * You should have received a copy of the GNU General Public License
 
21
 * along with this program; if not, write to the Free Software
 
22
 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
 
23
 * 02111-1307, USA.
 
24
 */
 
25
 
 
26
#include <config.h>
 
27
 
 
28
#include <glib/gi18n.h>
 
29
#include <string.h>
 
30
#include <gdk/gdk.h>
 
31
#include <gdk/gdkx.h>
 
32
#include <gnome-settings-daemon/gsd-enums.h>
 
33
#include <math.h>
 
34
 
 
35
#include "gnome-mouse-properties.h"
 
36
#include "gsd-input-helper.h"
 
37
 
 
38
#include <sys/types.h>
 
39
#include <sys/stat.h>
 
40
#include <dirent.h>
 
41
 
 
42
#include <X11/Xatom.h>
 
43
#include <X11/extensions/XInput.h>
 
44
 
 
45
#define WID(x) (GtkWidget*) gtk_builder_get_object (dialog, x)
 
46
 
 
47
static GSettings *mouse_settings = NULL;
 
48
static GSettings *touchpad_settings = NULL;
 
49
static GdkDeviceManager *device_manager = NULL;
 
50
static guint device_added_id = 0;
 
51
static guint device_removed_id = 0;
 
52
static gboolean changing_scroll = FALSE;
 
53
 
 
54
static void
 
55
orientation_radio_button_release_event (GtkWidget   *widget,
 
56
                                        GdkEventButton *event)
 
57
{
 
58
        gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (widget), TRUE);
 
59
}
 
60
 
 
61
static void
 
62
setup_scrollmethod_radios (GtkBuilder *dialog)
 
63
{
 
64
        GsdTouchpadScrollMethod method;
 
65
        gboolean active;
 
66
 
 
67
        method = g_settings_get_enum (touchpad_settings, "scroll-method");
 
68
        active = (method == GSD_TOUCHPAD_SCROLL_METHOD_TWO_FINGER_SCROLLING);
 
69
        gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (WID ("two_finger_scroll_toggle")), active);
 
70
}
 
71
 
 
72
static void
 
73
scrollmethod_changed_event (GtkToggleButton *button, GtkBuilder *dialog)
 
74
{
 
75
        GsdTouchpadScrollMethod method;
 
76
 
 
77
        if (changing_scroll)
 
78
                return;
 
79
 
 
80
        if (gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (WID ("two_finger_scroll_toggle"))))
 
81
                method = GSD_TOUCHPAD_SCROLL_METHOD_TWO_FINGER_SCROLLING;
 
82
        else
 
83
                method = GSD_TOUCHPAD_SCROLL_METHOD_EDGE_SCROLLING;
 
84
 
 
85
        g_settings_set_enum (touchpad_settings, "scroll-method", method);
 
86
}
 
87
 
 
88
static void
 
89
synaptics_check_capabilities (GtkBuilder *dialog)
 
90
{
 
91
        int numdevices, i;
 
92
        XDeviceInfo *devicelist;
 
93
        Atom realtype, prop;
 
94
        int realformat;
 
95
        unsigned long nitems, bytes_after;
 
96
        unsigned char *data;
 
97
 
 
98
        prop = XInternAtom (GDK_DISPLAY_XDISPLAY (gdk_display_get_default ()), "Synaptics Capabilities", True);
 
99
        if (!prop)
 
100
                return;
 
101
 
 
102
        devicelist = XListInputDevices (GDK_DISPLAY_XDISPLAY (gdk_display_get_default ()), &numdevices);
 
103
        for (i = 0; i < numdevices; i++) {
 
104
                if (devicelist[i].use != IsXExtensionPointer)
 
105
                        continue;
 
106
 
 
107
                gdk_error_trap_push ();
 
108
                XDevice *device = XOpenDevice (GDK_DISPLAY_XDISPLAY (gdk_display_get_default ()),
 
109
                                               devicelist[i].id);
 
110
                if (gdk_error_trap_pop ())
 
111
                        continue;
 
112
 
 
113
                gdk_error_trap_push ();
 
114
                if ((XGetDeviceProperty (GDK_DISPLAY_XDISPLAY (gdk_display_get_default ()), device, prop, 0, 2, False,
 
115
                                         XA_INTEGER, &realtype, &realformat, &nitems,
 
116
                                         &bytes_after, &data) == Success) && (realtype != None)) {
 
117
                        /* Property data is booleans for has_left, has_middle, has_right, has_double, has_triple.
 
118
                         * Newer drivers (X.org/kerrnel) will also include has_pressure and has_width. */
 
119
                        if (!data[0]) {
 
120
                                gtk_widget_set_sensitive (WID ("tap_to_click_toggle"), FALSE);
 
121
                        }
 
122
 
 
123
                        /* Disable two finger scrolling unless the hardware supports
 
124
                         * double touch */
 
125
                        if (!(data[3]))
 
126
                                gtk_widget_set_sensitive (WID ("two_finger_scroll_toggle"), FALSE);
 
127
 
 
128
                        XFree (data);
 
129
                }
 
130
                gdk_error_trap_pop_ignored ();
 
131
 
 
132
                XCloseDevice (GDK_DISPLAY_XDISPLAY (gdk_display_get_default ()), device);
 
133
        }
 
134
        XFreeDeviceList (devicelist);
 
135
}
 
136
 
 
137
static void
 
138
pointer_speed_scale_event (GtkRange *scale, GtkBuilder *dialog)
 
139
{
 
140
        gdouble value;
 
141
        GSettings *settings;
 
142
        GtkAdjustment *adjustment;
 
143
 
 
144
        if (GTK_WIDGET (scale) == WID ("pointer_speed_scale"))
 
145
                settings = mouse_settings;
 
146
        else
 
147
                settings = touchpad_settings;
 
148
 
 
149
        g_settings_set_double (settings, "motion-acceleration", gtk_range_get_value (scale));
 
150
 
 
151
        adjustment = gtk_range_get_adjustment (scale);
 
152
        value = gtk_adjustment_get_upper (adjustment) - gtk_range_get_value (scale) + 1;
 
153
        g_settings_set_int (settings, "motion-threshold", value);
 
154
}
 
155
 
 
156
/* Set up the property editors in the dialog. */
 
157
static void
 
158
setup_dialog (GtkBuilder *dialog)
 
159
{
 
160
        GtkRadioButton *radio;
 
161
        gboolean        touchpad_present, mouse_present;
 
162
 
 
163
        /* Orientation radio buttons */
 
164
        radio = GTK_RADIO_BUTTON (WID ("left_handed_radio"));
 
165
        g_settings_bind (mouse_settings, "left-handed", radio, "active", G_SETTINGS_BIND_DEFAULT);
 
166
 
 
167
        /* explicitly connect to button-release so that you can change orientation with either button */
 
168
        g_signal_connect (WID ("right_handed_radio"), "button_release_event",
 
169
                G_CALLBACK (orientation_radio_button_release_event), NULL);
 
170
        g_signal_connect (WID ("left_handed_radio"), "button_release_event",
 
171
                G_CALLBACK (orientation_radio_button_release_event), NULL);
 
172
 
 
173
        /* Double-click time */
 
174
        g_settings_bind (mouse_settings, "double-click",
 
175
                         gtk_range_get_adjustment (GTK_RANGE (WID ("double_click_scale"))), "value",
 
176
                         G_SETTINGS_BIND_DEFAULT);
 
177
 
 
178
        /* Mouse section */
 
179
        mouse_present = mouse_is_present ();
 
180
        gtk_widget_set_visible (WID ("mouse_vbox"), mouse_present);
 
181
 
 
182
        g_signal_connect (WID ("pointer_speed_scale"), "value-changed",
 
183
                          G_CALLBACK (pointer_speed_scale_event), dialog);
 
184
        g_settings_bind (mouse_settings, "motion-acceleration",
 
185
                         gtk_range_get_adjustment (GTK_RANGE (WID ("pointer_speed_scale"))), "value",
 
186
                         G_SETTINGS_BIND_DEFAULT);
 
187
 
 
188
        /* Trackpad page */
 
189
        touchpad_present = touchpad_is_present ();
 
190
        gtk_widget_set_visible (WID ("touchpad_vbox"), touchpad_present);
 
191
 
 
192
        g_settings_bind (touchpad_settings, "touchpad-enabled",
 
193
                         WID ("touchpad_enabled_switch"), "active",
 
194
                         G_SETTINGS_BIND_DEFAULT);
 
195
        g_settings_bind (touchpad_settings, "touchpad-enabled",
 
196
                         WID ("touchpad_options_box"), "sensitive",
 
197
                         G_SETTINGS_BIND_GET);
 
198
 
 
199
        g_settings_bind (touchpad_settings, "disable-while-typing",
 
200
                         WID ("disable_w_typing_toggle"), "active",
 
201
                         G_SETTINGS_BIND_DEFAULT);
 
202
        g_settings_bind (touchpad_settings, "tap-to-click",
 
203
                         WID ("tap_to_click_toggle"), "active",
 
204
                         G_SETTINGS_BIND_DEFAULT);
 
205
        g_settings_bind (touchpad_settings, "natural-scroll",
 
206
                         WID ("natural_scroll_toggle"), "active",
 
207
                         G_SETTINGS_BIND_DEFAULT);
 
208
        g_settings_bind (touchpad_settings, "motion-acceleration",
 
209
                         gtk_range_get_adjustment (GTK_RANGE (WID ("touchpad_pointer_speed_scale"))), "value",
 
210
                         G_SETTINGS_BIND_DEFAULT);
 
211
 
 
212
        g_signal_connect (WID ("touchpad_pointer_speed_scale"), "value-changed",
 
213
                          G_CALLBACK (pointer_speed_scale_event), dialog);
 
214
 
 
215
        if (touchpad_present) {
 
216
                synaptics_check_capabilities (dialog);
 
217
                setup_scrollmethod_radios (dialog);
 
218
        }
 
219
 
 
220
        g_signal_connect (WID ("two_finger_scroll_toggle"), "toggled",
 
221
                          G_CALLBACK (scrollmethod_changed_event), dialog);
 
222
}
 
223
 
 
224
/* Construct the dialog */
 
225
 
 
226
static void
 
227
create_dialog (GtkBuilder *dialog)
 
228
{
 
229
        GtkSizeGroup *size_group;
 
230
 
 
231
        size_group = gtk_size_group_new (GTK_SIZE_GROUP_HORIZONTAL);
 
232
        gtk_size_group_add_widget (size_group, WID ("primary_button_label"));
 
233
        gtk_size_group_add_widget (size_group, WID ("pointer_speed_label"));
 
234
        gtk_size_group_add_widget (size_group, WID ("double_click_label"));
 
235
        gtk_size_group_add_widget (size_group, WID ("touchpad_pointer_speed_label"));
 
236
 
 
237
        size_group = gtk_size_group_new (GTK_SIZE_GROUP_HORIZONTAL);
 
238
        gtk_size_group_add_widget (size_group, WID ("pointer_speed_fast_label"));
 
239
        gtk_size_group_add_widget (size_group, WID ("double_click_fast_label"));
 
240
        gtk_size_group_add_widget (size_group, WID ("touchpad_pointer_speed_fast_label"));
 
241
 
 
242
        size_group = gtk_size_group_new (GTK_SIZE_GROUP_HORIZONTAL);
 
243
        gtk_size_group_add_widget (size_group, WID ("pointer_speed_slow_label"));
 
244
        gtk_size_group_add_widget (size_group, WID ("double_click_slow_label"));
 
245
        gtk_size_group_add_widget (size_group, WID ("touchpad_pointer_speed_slow_label"));
 
246
 
 
247
        gtk_widget_set_direction (WID ("primary_button_box"), GTK_TEXT_DIR_LTR);
 
248
}
 
249
 
 
250
/* Callback issued when a button is clicked on the dialog */
 
251
 
 
252
static void
 
253
device_changed (GdkDeviceManager *device_manager,
 
254
                GdkDevice        *device,
 
255
                GtkBuilder       *dialog)
 
256
{
 
257
        gboolean present;
 
258
 
 
259
        present = touchpad_is_present ();
 
260
        gtk_widget_set_visible (WID ("touchpad_vbox"), present);
 
261
 
 
262
        if (present) {
 
263
                changing_scroll = TRUE;
 
264
                synaptics_check_capabilities (dialog);
 
265
                setup_scrollmethod_radios (dialog);
 
266
                changing_scroll = FALSE;
 
267
        }
 
268
 
 
269
        present = mouse_is_present ();
 
270
        gtk_widget_set_visible (WID ("mouse_vbox"), present);
 
271
}
 
272
 
 
273
GtkWidget *
 
274
gnome_mouse_properties_init (GtkBuilder *dialog)
 
275
{
 
276
        mouse_settings = g_settings_new ("org.gnome.settings-daemon.peripherals.mouse");
 
277
        touchpad_settings = g_settings_new ("org.gnome.settings-daemon.peripherals.touchpad");
 
278
 
 
279
        device_manager = gdk_display_get_device_manager (gdk_display_get_default ());
 
280
        device_added_id = g_signal_connect (device_manager, "device-added",
 
281
                                            G_CALLBACK (device_changed), dialog);
 
282
        device_removed_id = g_signal_connect (device_manager, "device-removed",
 
283
                                              G_CALLBACK (device_changed), dialog);
 
284
 
 
285
        create_dialog (dialog);
 
286
        setup_dialog (dialog);
 
287
 
 
288
        return WID ("mouse_properties_dialog");
 
289
}
 
290
 
 
291
void
 
292
gnome_mouse_properties_dispose (GtkWidget *widget)
 
293
{
 
294
        if (mouse_settings != NULL) {
 
295
                g_object_unref (mouse_settings);
 
296
                mouse_settings = NULL;
 
297
        }
 
298
        if (touchpad_settings != NULL) {
 
299
                g_object_unref (touchpad_settings);
 
300
                touchpad_settings = NULL;
 
301
        }
 
302
        if (device_manager != NULL) {
 
303
                g_signal_handler_disconnect (device_manager, device_added_id);
 
304
                device_added_id = 0;
 
305
                g_signal_handler_disconnect (device_manager, device_removed_id);
 
306
                device_removed_id = 0;
 
307
                device_manager = NULL;
 
308
        }
 
309
}