Merge lp:~jderose/ubuntu/saucy/gnome-settings-daemon/tune-syndaemon2 into lp:ubuntu/saucy/gnome-settings-daemon

Proposed by Jason Gerard DeRose
Status: Needs review
Proposed branch: lp:~jderose/ubuntu/saucy/gnome-settings-daemon/tune-syndaemon2
Merge into: lp:ubuntu/saucy/gnome-settings-daemon
Diff against target: 4202 lines (+1384/-2531)
9 files modified
.pc/applied-patches (+1/-0)
.pc/git_keybindings_add_screen_reader_toggle.patch/data/org.gnome.settings-daemon.plugins.media-keys.gschema.xml.in.in (+0/-212)
.pc/sync_input_sources_to_accountsservice.patch/configure.ac (+0/-609)
.pc/sync_input_sources_to_accountsservice.patch/plugins/keyboard/gsd-keyboard-manager.c (+0/-1708)
.pc/tune-syndaemon.patch/plugins/mouse/gsd-mouse-manager.c (+1354/-0)
debian/changelog (+7/-0)
debian/patches/series (+1/-0)
debian/patches/tune-syndaemon.patch (+20/-0)
plugins/mouse/gsd-mouse-manager.c (+1/-2)
To merge this branch: bzr merge lp:~jderose/ubuntu/saucy/gnome-settings-daemon/tune-syndaemon2
Reviewer Review Type Date Requested Status
Luke Yelavich (community) Needs Information
Review via email: mp+181565@code.launchpad.net

Description of the change

See https://bugs.launchpad.net/ubuntu/+source/gnome-settings-daemon/+bug/1215463

On a modern laptop with a large touchpad/clickpad, your palms tend to brush the touch surface as you type. The problem is that on Ubuntu, this creates an annoying amount of cursor wiggle. Competing platforms don't have this problem, so this needs to be improved on Ubuntu.

Part of the problem is the is that `xserver-xorg-input-synaptics` driver doesn't do effective palm detection (it seems), and part of the problem is that `gnome-settings-daemon` launches `syndaemon` such that it *never* disables cursor movement.

Currently syndaemon is launched like this:

  syndaemon -i 1.0 -t -K -R

The "-t" option tells syndaemon to never block cursor movement. It will only block accidental vertical scrolling (which is darn near impossible to do on a modern system with two finger scrolling), and block accidental tap-to-click (which seems unlikely something you can do by mistake with your palms). So from a user perspective, "Disable while typing" currently does nothing.

I'm proposing that syndaemon instead be launched like this:

  syndaemon -i 0.5 -K -R

Without the "-t" option, syndaemon will block cursor movement, vertical scrolling, and tap-to-click. And the "-i 0.5" means it will block it for 500ms (half a second).

System76 has been shipping a patched `gnome-settings-daemon` (Raring) on all our products for the last two months, and we've received no support issues about it (if this caused noticeable usability issues, I'm confident we'd have heard about it).

We've also done a lot of testing and tuning on the timeout threshold, and 500ms seems like about the sweet spot. It's long enough to be decently effective for most typists, but not so long that the user will catch the trackpad still disabled when they move from typing back to "cursoring" :P

Note that this isn't a prefect solution, and you really can't do this especially well with a static timeout anyway (would be better to be dynamic based on typing speed). For slow typists, 500ms often isn't long enough. But for now, I feel it's better to find that sweet spot where it at least gives some improvement for most users, without causing any negative impact for any users.

To post a comment you must log in.
Revision history for this message
Jason Gerard DeRose (jderose) wrote :

Question: as far as I know, you're supposed to add changes in the .pc directory for UDD workflow. Just wanted to double check as this diff looks like such a mess :)

Revision history for this message
Luke Yelavich (themuso) wrote :

Given this is the upstrea default, I wonder whether its worth discussing it upstream. WHilst this is a trivial patch, it is yet another patch that Ubuntu has to carry, and we already carry a lot of patches against this package.

I suggest filing a bug upstream and discussing the desire to remove the -t flag, and indeed discuss why upstream decided to use the -t flag in the first place.

review: Needs Information
Revision history for this message
Jason Gerard DeRose (jderose) wrote :

Thanks for the feedback, Luke!

Yes, I plan on discussing this upstream, but I'd first like to get consensus from Ubuntu on this change, as it doesn't help System76 if the change is accepted upstream but Ubuntu disagrees with it.

Also as Ubuntu isn't tracking the upstream gnome-settings-daemon releases closely anymore, it will likely take more than one full cycle by the time the change would land in Ubuntu. Based on the current pattern, if we got this change accepted into gnome-settings-daemon 3.10, it wouldn't land in Ubuntu till Ubuntu 14.10.

For what it's worth, it would really help System76 if this change could be accepted into Saucy, as then we don't have to maintained a patched version in our PPA.

254. By Jason Gerard DeRose

Merged 3.6.4-0ubuntu17 from lp:ubuntu/saucy/gnome-settings-daemon

255. By Jason Gerard DeRose

Added 3.6.4-0ubuntu18 entry in changelog

256. By Jason Gerard DeRose

Added DEP-3 headers to tune-syndaemon.patch

257. By Jason Gerard DeRose

Clearer

258. By Jason Gerard DeRose

Merged from 3.6.4-0ubuntu19 lp:ubuntu/saucy/gnome-settings-daemon

259. By Jason Gerard DeRose

Add changelog entry for 3.6.4-0ubuntu20

Revision history for this message
Doug McMahon (mc3man) wrote :

hope you all aren't going around in circles on this
The current settings are the result of this bug, caused when g-s-d went to 2 sec
https://bugs.launchpad.net/ubuntu/+source/gnome-settings-daemon/+bug/801763

That resulted in this bug, maybe others
https://bugs.launchpad.net/ubuntu/+source/gnome-settings-daemon/+bug/962958

And the current settings from
https://bugzilla.gnome.org/show_bug.cgi?id=673055

Unmerged revisions

259. By Jason Gerard DeRose

Add changelog entry for 3.6.4-0ubuntu20

258. By Jason Gerard DeRose

Merged from 3.6.4-0ubuntu19 lp:ubuntu/saucy/gnome-settings-daemon

257. By Jason Gerard DeRose

Clearer

256. By Jason Gerard DeRose

Added DEP-3 headers to tune-syndaemon.patch

255. By Jason Gerard DeRose

Added 3.6.4-0ubuntu18 entry in changelog

254. By Jason Gerard DeRose

Merged 3.6.4-0ubuntu17 from lp:ubuntu/saucy/gnome-settings-daemon

253. By Jason Gerard DeRose

Updated changelog

252. By Jason Gerard DeRose

Added tune-syndaemon.patch so that syndaemon is called with '-i 0.5 -K -R'

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
=== modified file '.pc/applied-patches'
--- .pc/applied-patches 2013-08-29 16:10:41 +0000
+++ .pc/applied-patches 2013-08-29 18:58:42 +0000
@@ -31,3 +31,4 @@
31git_keyboard_Adapt_to_gnome_xkb_info_API_change.patch31git_keyboard_Adapt_to_gnome_xkb_info_API_change.patch
32git_keyboard_Adapt_to_gnome_xkb_info_API_change_2.patch32git_keyboard_Adapt_to_gnome_xkb_info_API_change_2.patch
33git_keybindings_add_screen_reader_toggle.patch33git_keybindings_add_screen_reader_toggle.patch
34tune-syndaemon.patch
3435
=== added directory '.pc/git_keybindings_add_screen_reader_toggle.patch'
=== removed directory '.pc/git_keybindings_add_screen_reader_toggle.patch'
=== added directory '.pc/git_keybindings_add_screen_reader_toggle.patch/data'
=== removed directory '.pc/git_keybindings_add_screen_reader_toggle.patch/data'
=== added file '.pc/git_keybindings_add_screen_reader_toggle.patch/data/org.gnome.settings-daemon.plugins.media-keys.gschema.xml.in.in'
--- .pc/git_keybindings_add_screen_reader_toggle.patch/data/org.gnome.settings-daemon.plugins.media-keys.gschema.xml.in.in 1970-01-01 00:00:00 +0000
+++ .pc/git_keybindings_add_screen_reader_toggle.patch/data/org.gnome.settings-daemon.plugins.media-keys.gschema.xml.in.in 2013-08-29 18:58:42 +0000
@@ -0,0 +1,212 @@
1<schemalist>
2 <schema gettext-domain="@GETTEXT_PACKAGE@" id="org.gnome.settings-daemon.plugins.media-keys" path="/org/gnome/settings-daemon/plugins/media-keys/">
3 <key name="active" type="b">
4 <default>true</default>
5 <_summary>Activation of this plugin</_summary>
6 <_description>Whether this plugin would be activated by gnome-settings-daemon or not</_description>
7 </key>
8 <key name="custom-keybindings" type="as">
9 <default>[]</default>
10 <_summary>Custom keybindings</_summary>
11 <_description>List of custom keybindings</_description>
12 </key>
13 <key name="calculator" type="s">
14 <default>'XF86Calculator'</default>
15 <_summary>Launch calculator</_summary>
16 <_description>Binding to launch the calculator.</_description>
17 </key>
18 <key name="email" type="s">
19 <default>'XF86Mail'</default>
20 <_summary>Launch email client</_summary>
21 <_description>Binding to launch the email client.</_description>
22 </key>
23 <key name="eject" type="s">
24 <default>'XF86Eject'</default>
25 <_summary>Eject</_summary>
26 <_description>Binding to eject an optical disc.</_description>
27 </key>
28 <key name="help" type="s">
29 <default>''</default>
30 <_summary>Launch help browser</_summary>
31 <_description>Binding to launch the help browser.</_description>
32 </key>
33 <key name="home" type="s">
34 <default>'XF86Explorer'</default>
35 <_summary>Home folder</_summary>
36 <_description>Binding to open the Home folder.</_description>
37 </key>
38 <key name="media" type="s">
39 <default>'XF86AudioMedia'</default>
40 <_summary>Launch media player</_summary>
41 <_description>Binding to launch the media player.</_description>
42 </key>
43 <key name="next" type="s">
44 <default>'XF86AudioNext'</default>
45 <_summary>Next track</_summary>
46 <_description>Binding to skip to next track.</_description>
47 </key>
48 <key name="pause" type="s">
49 <default>'XF86AudioPause'</default>
50 <_summary>Pause playback</_summary>
51 <_description>Binding to pause playback.</_description>
52 </key>
53 <key name="play" type="s">
54 <default>'XF86AudioPlay'</default>
55 <_summary>Play (or play/pause)</_summary>
56 <_description>Binding to start playback (or toggle play/pause).</_description>
57 </key>
58 <key name="logout" type="s">
59 <default>'&lt;Control&gt;&lt;Alt&gt;Delete'</default>
60 <_summary>Log out</_summary>
61 <_description>Binding to log out.</_description>
62 </key>
63 <key name="previous" type="s">
64 <default>'XF86AudioPrev'</default>
65 <_summary>Previous track</_summary>
66 <_description>Binding to skip to previous track.</_description>
67 </key>
68 <key name="priority" type="i">
69 <default>98</default>
70 <_summary>Priority to use for this plugin</_summary>
71 <_description>Priority to use for this plugin in gnome-settings-daemon startup queue</_description>
72 </key>
73 <key name="screensaver" type="s">
74 <default>'&lt;Control&gt;&lt;Alt&gt;l'</default>
75 <_summary>Lock screen</_summary>
76 <_description>Binding to lock the screen.</_description>
77 </key>
78 <key name="search" type="s">
79 <default>'XF86Search'</default>
80 <_summary>Search</_summary>
81 <_description>Binding to launch the search tool.</_description>
82 </key>
83 <key name="stop" type="s">
84 <default>'XF86AudioStop'</default>
85 <_summary>Stop playback</_summary>
86 <_description>Binding to stop playback.</_description>
87 </key>
88 <key name="volume-down" type="s">
89 <default>'XF86AudioLowerVolume'</default>
90 <_summary>Volume down</_summary>
91 <_description>Binding to lower the system volume.</_description>
92 </key>
93 <key name="volume-mute" type="s">
94 <default>'XF86AudioMute'</default>
95 <_summary>Volume mute</_summary>
96 <_description>Binding to mute the system volume.</_description>
97 </key>
98 <key name="volume-up" type="s">
99 <default>'XF86AudioRaiseVolume'</default>
100 <_summary>Volume up</_summary>
101 <_description>Binding to raise the system volume.</_description>
102 </key>
103 <key name="screenshot" type="s">
104 <default>'Print'</default>
105 <_summary>Take a screenshot</_summary>
106 <_description>Binding to take a screenshot.</_description>
107 </key>
108 <key name="window-screenshot" type="s">
109 <default>'&lt;Alt&gt;Print'</default>
110 <_summary>Take a screenshot of a window</_summary>
111 <_description>Binding to take a screenshot of a window.</_description>
112 </key>
113 <key name="area-screenshot" type="s">
114 <default>'&lt;Shift&gt;Print'</default>
115 <_summary>Take a screenshot of an area</_summary>
116 <_description>Binding to take a screenshot of an area.</_description>
117 </key>
118 <key name="screenshot-clip" type="s">
119 <default>'&lt;Ctrl&gt;Print'</default>
120 <_summary>Copy a screenshot to clipboard</_summary>
121 <_description>Binding to copy a screenshot to clipboard.</_description>
122 </key>
123 <key name="window-screenshot-clip" type="s">
124 <default>'&lt;Ctrl&gt;&lt;Alt&gt;Print'</default>
125 <_summary>Copy a screenshot of a window to clipboard</_summary>
126 <_description>Binding to copy a screenshot of a window to clipboard.</_description>
127 </key>
128 <key name="area-screenshot-clip" type="s">
129 <default>'&lt;Ctrl&gt;&lt;Shift&gt;Print'</default>
130 <_summary>Copy a screenshot of an area to clipboard</_summary>
131 <_description>Binding to copy a screenshot of an area to clipboard.</_description>
132 </key>
133 <key name="terminal" type="s">
134 <default>'&lt;Primary&gt;&lt;Alt&gt;t'</default>
135 <_summary>Launch terminal</_summary>
136 <_description>Binding to launch the terminal.</_description>
137 </key>
138 <key name="www" type="s">
139 <default>'XF86WWW'</default>
140 <_summary>Launch web browser</_summary>
141 <_description>Binding to launch the web browser.</_description>
142 </key>
143 <key name="magnifier" type="s">
144 <default>'&lt;Alt&gt;&lt;Super&gt;8'</default>
145 <_summary>Toggle magnifier</_summary>
146 <_description>Binding to show the screen magnifier</_description>
147 </key>
148 <key name="screenreader" type="s">
149 <default>''</default>
150 <_summary>Toggle screen reader</_summary>
151 <_description>Binding to start the screen reader</_description>
152 </key>
153 <key name="on-screen-keyboard" type="s">
154 <default>''</default>
155 <_summary>Toggle on-screen keyboard</_summary>
156 <_description>Binding to show the on-screen keyboard</_description>
157 </key>
158 <key name="increase-text-size" type="s">
159 <default>''</default>
160 <_summary>Increase text size</_summary>
161 <_description>Binding to increase the text size</_description>
162 </key>
163 <key name="decrease-text-size" type="s">
164 <default>''</default>
165 <_summary>Decrease text size</_summary>
166 <_description>Binding to decrease the text size</_description>
167 </key>
168 <key name="toggle-contrast" type="s">
169 <default>''</default>
170 <_summary>Toggle contrast</_summary>
171 <_description>Binding to toggle the interface contrast</_description>
172 </key>
173 <key name="magnifier-zoom-in" type="s">
174 <default>'&lt;Alt&gt;&lt;Super&gt;equal'</default>
175 <_summary>Magnifier zoom in</_summary>
176 <_description>Binding for the magnifier to zoom in</_description>
177 </key>
178 <key name="magnifier-zoom-out" type="s">
179 <default>'&lt;Alt&gt;&lt;Super&gt;minus'</default>
180 <_summary>Magnifier zoom out</_summary>
181 <_description>Binding for the magnifier to zoom out</_description>
182 </key>
183 <key name="switch-input-source" type="s">
184 <default>''</default>
185 <_summary>Switch input source</_summary>
186 <_description>Binding to select the next input source</_description>
187 </key>
188 <key name="switch-input-source-backward" type="s">
189 <default>''</default>
190 <_summary>Switch input source backward</_summary>
191 <_description>Binding to select the previous input source</_description>
192 </key>
193 </schema>
194
195 <schema gettext-domain="@GETTEXT_PACKAGE@" id="org.gnome.settings-daemon.plugins.media-keys.custom-keybinding">
196 <key name="name" type="s">
197 <default>''</default>
198 <_summary>Name</_summary>
199 <_description>Name of the custom binding</_description>
200 </key>
201 <key name="binding" type="s">
202 <default>''</default>
203 <_summary>Binding</_summary>
204 <_description>Binding for the custom binding</_description>
205 </key>
206 <key name="command" type="s">
207 <default>''</default>
208 <_summary>Command</_summary>
209 <_description>Command to run when the binding is invoked</_description>
210 </key>
211 </schema>
212</schemalist>
0213
=== removed file '.pc/git_keybindings_add_screen_reader_toggle.patch/data/org.gnome.settings-daemon.plugins.media-keys.gschema.xml.in.in'
--- .pc/git_keybindings_add_screen_reader_toggle.patch/data/org.gnome.settings-daemon.plugins.media-keys.gschema.xml.in.in 2013-08-23 16:08:29 +0000
+++ .pc/git_keybindings_add_screen_reader_toggle.patch/data/org.gnome.settings-daemon.plugins.media-keys.gschema.xml.in.in 1970-01-01 00:00:00 +0000
@@ -1,212 +0,0 @@
1<schemalist>
2 <schema gettext-domain="@GETTEXT_PACKAGE@" id="org.gnome.settings-daemon.plugins.media-keys" path="/org/gnome/settings-daemon/plugins/media-keys/">
3 <key name="active" type="b">
4 <default>true</default>
5 <_summary>Activation of this plugin</_summary>
6 <_description>Whether this plugin would be activated by gnome-settings-daemon or not</_description>
7 </key>
8 <key name="custom-keybindings" type="as">
9 <default>[]</default>
10 <_summary>Custom keybindings</_summary>
11 <_description>List of custom keybindings</_description>
12 </key>
13 <key name="calculator" type="s">
14 <default>'XF86Calculator'</default>
15 <_summary>Launch calculator</_summary>
16 <_description>Binding to launch the calculator.</_description>
17 </key>
18 <key name="email" type="s">
19 <default>'XF86Mail'</default>
20 <_summary>Launch email client</_summary>
21 <_description>Binding to launch the email client.</_description>
22 </key>
23 <key name="eject" type="s">
24 <default>'XF86Eject'</default>
25 <_summary>Eject</_summary>
26 <_description>Binding to eject an optical disc.</_description>
27 </key>
28 <key name="help" type="s">
29 <default>''</default>
30 <_summary>Launch help browser</_summary>
31 <_description>Binding to launch the help browser.</_description>
32 </key>
33 <key name="home" type="s">
34 <default>'XF86Explorer'</default>
35 <_summary>Home folder</_summary>
36 <_description>Binding to open the Home folder.</_description>
37 </key>
38 <key name="media" type="s">
39 <default>'XF86AudioMedia'</default>
40 <_summary>Launch media player</_summary>
41 <_description>Binding to launch the media player.</_description>
42 </key>
43 <key name="next" type="s">
44 <default>'XF86AudioNext'</default>
45 <_summary>Next track</_summary>
46 <_description>Binding to skip to next track.</_description>
47 </key>
48 <key name="pause" type="s">
49 <default>'XF86AudioPause'</default>
50 <_summary>Pause playback</_summary>
51 <_description>Binding to pause playback.</_description>
52 </key>
53 <key name="play" type="s">
54 <default>'XF86AudioPlay'</default>
55 <_summary>Play (or play/pause)</_summary>
56 <_description>Binding to start playback (or toggle play/pause).</_description>
57 </key>
58 <key name="logout" type="s">
59 <default>'&lt;Control&gt;&lt;Alt&gt;Delete'</default>
60 <_summary>Log out</_summary>
61 <_description>Binding to log out.</_description>
62 </key>
63 <key name="previous" type="s">
64 <default>'XF86AudioPrev'</default>
65 <_summary>Previous track</_summary>
66 <_description>Binding to skip to previous track.</_description>
67 </key>
68 <key name="priority" type="i">
69 <default>98</default>
70 <_summary>Priority to use for this plugin</_summary>
71 <_description>Priority to use for this plugin in gnome-settings-daemon startup queue</_description>
72 </key>
73 <key name="screensaver" type="s">
74 <default>'&lt;Control&gt;&lt;Alt&gt;l'</default>
75 <_summary>Lock screen</_summary>
76 <_description>Binding to lock the screen.</_description>
77 </key>
78 <key name="search" type="s">
79 <default>'XF86Search'</default>
80 <_summary>Search</_summary>
81 <_description>Binding to launch the search tool.</_description>
82 </key>
83 <key name="stop" type="s">
84 <default>'XF86AudioStop'</default>
85 <_summary>Stop playback</_summary>
86 <_description>Binding to stop playback.</_description>
87 </key>
88 <key name="volume-down" type="s">
89 <default>'XF86AudioLowerVolume'</default>
90 <_summary>Volume down</_summary>
91 <_description>Binding to lower the system volume.</_description>
92 </key>
93 <key name="volume-mute" type="s">
94 <default>'XF86AudioMute'</default>
95 <_summary>Volume mute</_summary>
96 <_description>Binding to mute the system volume.</_description>
97 </key>
98 <key name="volume-up" type="s">
99 <default>'XF86AudioRaiseVolume'</default>
100 <_summary>Volume up</_summary>
101 <_description>Binding to raise the system volume.</_description>
102 </key>
103 <key name="screenshot" type="s">
104 <default>'Print'</default>
105 <_summary>Take a screenshot</_summary>
106 <_description>Binding to take a screenshot.</_description>
107 </key>
108 <key name="window-screenshot" type="s">
109 <default>'&lt;Alt&gt;Print'</default>
110 <_summary>Take a screenshot of a window</_summary>
111 <_description>Binding to take a screenshot of a window.</_description>
112 </key>
113 <key name="area-screenshot" type="s">
114 <default>'&lt;Shift&gt;Print'</default>
115 <_summary>Take a screenshot of an area</_summary>
116 <_description>Binding to take a screenshot of an area.</_description>
117 </key>
118 <key name="screenshot-clip" type="s">
119 <default>'&lt;Ctrl&gt;Print'</default>
120 <_summary>Copy a screenshot to clipboard</_summary>
121 <_description>Binding to copy a screenshot to clipboard.</_description>
122 </key>
123 <key name="window-screenshot-clip" type="s">
124 <default>'&lt;Ctrl&gt;&lt;Alt&gt;Print'</default>
125 <_summary>Copy a screenshot of a window to clipboard</_summary>
126 <_description>Binding to copy a screenshot of a window to clipboard.</_description>
127 </key>
128 <key name="area-screenshot-clip" type="s">
129 <default>'&lt;Ctrl&gt;&lt;Shift&gt;Print'</default>
130 <_summary>Copy a screenshot of an area to clipboard</_summary>
131 <_description>Binding to copy a screenshot of an area to clipboard.</_description>
132 </key>
133 <key name="terminal" type="s">
134 <default>'&lt;Primary&gt;&lt;Alt&gt;t'</default>
135 <_summary>Launch terminal</_summary>
136 <_description>Binding to launch the terminal.</_description>
137 </key>
138 <key name="www" type="s">
139 <default>'XF86WWW'</default>
140 <_summary>Launch web browser</_summary>
141 <_description>Binding to launch the web browser.</_description>
142 </key>
143 <key name="magnifier" type="s">
144 <default>'&lt;Alt&gt;&lt;Super&gt;8'</default>
145 <_summary>Toggle magnifier</_summary>
146 <_description>Binding to show the screen magnifier</_description>
147 </key>
148 <key name="screenreader" type="s">
149 <default>''</default>
150 <_summary>Toggle screen reader</_summary>
151 <_description>Binding to start the screen reader</_description>
152 </key>
153 <key name="on-screen-keyboard" type="s">
154 <default>''</default>
155 <_summary>Toggle on-screen keyboard</_summary>
156 <_description>Binding to show the on-screen keyboard</_description>
157 </key>
158 <key name="increase-text-size" type="s">
159 <default>''</default>
160 <_summary>Increase text size</_summary>
161 <_description>Binding to increase the text size</_description>
162 </key>
163 <key name="decrease-text-size" type="s">
164 <default>''</default>
165 <_summary>Decrease text size</_summary>
166 <_description>Binding to decrease the text size</_description>
167 </key>
168 <key name="toggle-contrast" type="s">
169 <default>''</default>
170 <_summary>Toggle contrast</_summary>
171 <_description>Binding to toggle the interface contrast</_description>
172 </key>
173 <key name="magnifier-zoom-in" type="s">
174 <default>'&lt;Alt&gt;&lt;Super&gt;equal'</default>
175 <_summary>Magnifier zoom in</_summary>
176 <_description>Binding for the magnifier to zoom in</_description>
177 </key>
178 <key name="magnifier-zoom-out" type="s">
179 <default>'&lt;Alt&gt;&lt;Super&gt;minus'</default>
180 <_summary>Magnifier zoom out</_summary>
181 <_description>Binding for the magnifier to zoom out</_description>
182 </key>
183 <key name="switch-input-source" type="s">
184 <default>''</default>
185 <_summary>Switch input source</_summary>
186 <_description>Binding to select the next input source</_description>
187 </key>
188 <key name="switch-input-source-backward" type="s">
189 <default>''</default>
190 <_summary>Switch input source backward</_summary>
191 <_description>Binding to select the previous input source</_description>
192 </key>
193 </schema>
194
195 <schema gettext-domain="@GETTEXT_PACKAGE@" id="org.gnome.settings-daemon.plugins.media-keys.custom-keybinding">
196 <key name="name" type="s">
197 <default>''</default>
198 <_summary>Name</_summary>
199 <_description>Name of the custom binding</_description>
200 </key>
201 <key name="binding" type="s">
202 <default>''</default>
203 <_summary>Binding</_summary>
204 <_description>Binding for the custom binding</_description>
205 </key>
206 <key name="command" type="s">
207 <default>''</default>
208 <_summary>Command</_summary>
209 <_description>Command to run when the binding is invoked</_description>
210 </key>
211 </schema>
212</schemalist>
2130
=== removed directory '.pc/sync_input_sources_to_accountsservice.patch'
=== removed file '.pc/sync_input_sources_to_accountsservice.patch/configure.ac'
--- .pc/sync_input_sources_to_accountsservice.patch/configure.ac 2013-08-29 16:10:41 +0000
+++ .pc/sync_input_sources_to_accountsservice.patch/configure.ac 1970-01-01 00:00:00 +0000
@@ -1,609 +0,0 @@
1AC_PREREQ([2.60])
2
3AC_INIT([gnome-settings-daemon],
4 [3.6.4],
5 [http://bugzilla.gnome.org/enter_bug.cgi?product=gnome-settings-daemon])
6
7AC_CONFIG_SRCDIR([gnome-settings-daemon/gnome-settings-manager.c])
8
9AM_INIT_AUTOMAKE([1.9 tar-ustar dist-xz no-dist-gzip check-news])
10AM_MAINTAINER_MODE([enable])
11
12m4_ifdef([AM_SILENT_RULES],[AM_SILENT_RULES([yes])])
13
14m4_define([gsd_api_version_major],[3])
15m4_define([gsd_api_version_minor],[0])
16m4_define([gsd_api_version],[gsd_api_version_major.gsd_api_version_minor])
17GSD_API_VERSION="gsd_api_version"
18AC_SUBST(GSD_API_VERSION)
19
20AC_STDC_HEADERS
21AC_PROG_CXX
22AM_PROG_CC_C_O
23AC_PROG_LIBTOOL
24
25AC_HEADER_STDC
26
27AC_SUBST(VERSION)
28
29AC_CONFIG_HEADERS([config.h])
30
31IT_PROG_INTLTOOL([0.37.1])
32
33GETTEXT_PACKAGE=gnome-settings-daemon
34AC_SUBST(GETTEXT_PACKAGE)
35AC_DEFINE_UNQUOTED(GETTEXT_PACKAGE, "$GETTEXT_PACKAGE", [Name of default gettext domain])
36
37AM_GLIB_GNU_GETTEXT
38
39GSD_INTLTOOL_PLUGIN_RULE='%.gnome-settings-plugin: %.gnome-settings-plugin.in $(INTLTOOL_MERGE) $(wildcard $(top_srcdir)/po/*.po) ; LC_ALL=C $(INTLTOOL_MERGE) -d -u -c $(top_builddir)/po/.intltool-merge-cache $(top_srcdir)/po $< [$]@'
40AC_SUBST([GSD_INTLTOOL_PLUGIN_RULE])
41
42dnl ---------------------------------------------------------------------------
43dnl - Dependencies
44dnl ---------------------------------------------------------------------------
45
46GLIB_REQUIRED_VERSION=2.31.0
47GTK_REQUIRED_VERSION=3.3.18
48GCONF_REQUIRED_VERSION=2.6.1
49GIO_REQUIRED_VERSION=2.26.0
50GNOME_DESKTOP_REQUIRED_VERSION=3.5.3
51LIBNOTIFY_REQUIRED_VERSION=0.7.3
52UPOWER_GLIB_REQUIRED_VERSION=0.9.1
53PA_REQUIRED_VERSION=0.9.16
54LIBWACOM_REQUIRED_VERSION=0.6
55UPOWER_REQUIRED_VERSION=0.9.11
56APPINDICATOR_REQUIRED_VERSION=0.3.0
57IBUS_REQUIRED_VERSION=1.4.99
58
59EXTRA_COMPILE_WARNINGS(yes)
60
61PKG_CHECK_MODULES(SETTINGS_DAEMON,
62 glib-2.0 >= $GLIB_REQUIRED_VERSION
63 gtk+-3.0 >= $GTK_REQUIRED_VERSION
64 gio-2.0 >= $GIO_REQUIRED_VERSION
65 gmodule-2.0
66 gthread-2.0
67 gsettings-desktop-schemas >= 3.5.90
68)
69
70PKG_CHECK_MODULES(SETTINGS_PLUGIN,
71 gtk+-3.0 >= $GTK_REQUIRED_VERSION
72 gio-2.0 >= $GIO_REQUIRED_VERSION
73 libnotify >= $LIBNOTIFY_REQUIRED_VERSION
74 gsettings-desktop-schemas
75 x11
76)
77
78GSD_PLUGIN_LDFLAGS="-export_dynamic -module -avoid-version -no-undefined"
79case $host_os in
80 darwin*)
81 GSD_PLUGIN_LDFLAGS="${GSD_PLUGIN_LDFLAGS} -Wl,-bundle_loader,\$(top_builddir)/gnome-settings-daemon/gnome-settings-daemon"
82 ;;
83esac
84AC_SUBST([GSD_PLUGIN_LDFLAGS])
85
86AC_PATH_PROG(GLIB_GENMARSHAL, glib-genmarshal)
87
88dnl ================================================================
89dnl GSettings stuff
90dnl ================================================================
91
92GLIB_GSETTINGS
93
94dnl ---------------------------------------------------------------------------
95dnl - Check for gnome-desktop
96dnl ---------------------------------------------------------------------------
97PKG_CHECK_MODULES(GNOME_DESKTOP, gnome-desktop-3.0 >= $GNOME_DESKTOP_REQUIRED_VERSION)
98
99dnl ---------------------------------------------------------------------------
100dnl - Check for LCMS2
101dnl ---------------------------------------------------------------------------
102PKG_CHECK_MODULES(LCMS, lcms2 >= 2.2, have_new_lcms=yes, have_new_lcms=no)
103if test x$have_new_lcms = xyes; then
104 AC_DEFINE(HAVE_NEW_LCMS,1,[Got new lcms2])
105else
106 PKG_CHECK_MODULES(LCMS, lcms2)
107fi
108
109dnl ---------------------------------------------------------------------------
110dnl - Check for libnotify
111dnl ---------------------------------------------------------------------------
112
113PKG_CHECK_MODULES(LIBNOTIFY, libnotify >= $LIBNOTIFY_REQUIRED_VERSION,
114 [have_libnotify=yes], have_libnotify=no)
115if test "x$have_libnotify" = xno ; then
116 AC_MSG_ERROR([libnotify is required to build gnome-settings-daemon])
117fi
118AC_SUBST(LIBNOTIFY_CFLAGS)
119AC_SUBST(LIBNOTIFY_LIBS)
120
121dnl ---------------------------------------------------------------------------
122dnl - GUdev integration (default enabled)
123dnl ---------------------------------------------------------------------------
124GUDEV_PKG=""
125AC_ARG_ENABLE(gudev, AS_HELP_STRING([--disable-gudev],[Disable GUdev support (not optional on Linux platforms)]), enable_gudev=$enableval)
126if test x$enable_gudev != xno; then
127 PKG_CHECK_MODULES(GUDEV, gudev-1.0, have_gudev="yes", have_gudev="no")
128 if test "x$have_gudev" = "xyes"; then
129 AC_DEFINE(HAVE_GUDEV, 1, [define if GUdev is available])
130 GUDEV_PKG="gudev-1.0"
131 else
132 if test x$enable_gudev = xyes; then
133 AC_MSG_ERROR([GUdev enabled but not found])
134 fi
135 fi
136else
137 have_gudev=no
138fi
139AM_CONDITIONAL(HAVE_GUDEV, test x$have_gudev = xyes)
140
141dnl ---------------------------------------------------------------------------
142dnl - common
143dnl ---------------------------------------------------------------------------
144
145PKG_CHECK_MODULES(COMMON, x11 kbproto xi)
146
147dnl ---------------------------------------------------------------------------
148dnl - automount
149dnl ---------------------------------------------------------------------------
150
151PKG_CHECK_MODULES(AUTOMOUNT, x11 kbproto)
152
153dnl ---------------------------------
154dnl - Application indicator
155dnl ---------------------------------
156
157AC_ARG_ENABLE([appindicator],
158 AS_HELP_STRING([--enable-appindicator[=@<:@no/auto/yes@:>@]],[Build support for application indicators]),
159 [enable_appindicator=$enableval],
160 [enable_appindicator="auto"])
161
162
163if test x$enable_appindicator = xauto ; then
164 PKG_CHECK_EXISTS(appindicator3-0.1 >= $APPINDICATOR_REQUIRED_VERSION,
165 [enable_appindicator="yes"],
166 [enable_appindicator="no"])
167fi
168
169if test x$enable_appindicator = xyes ; then
170 PKG_CHECK_MODULES(APPINDICATOR,
171 [appindicator3-0.1 >= $APPINDICATOR_REQUIRED_VERSION],
172 [AC_DEFINE(HAVE_APPINDICATOR, 1, [Have AppIndicator])])
173fi
174
175AM_CONDITIONAL(HAVE_APPINDICATOR, test x$enable_appindicator = xyes)
176AC_SUBST(APPINDICATOR_CFLAGS)
177AC_SUBST(APPINDICATOR_LIBS)
178
179dnl ---------------------------------------------------------------------------
180dnl - background
181dnl ---------------------------------------------------------------------------
182
183PKG_CHECK_MODULES(BACKGROUND, x11 gnome-desktop-3.0 >= $GNOME_DESKTOP_REQUIRED_VERSION)
184
185dnl ---------------------------------------------------------------------------
186dnl - mouse
187dnl ---------------------------------------------------------------------------
188
189PKG_CHECK_MODULES(MOUSE, x11 xi)
190
191dnl ---------------------------------------------------------------------------
192dnl - cursor
193dnl ---------------------------------------------------------------------------
194
195PKG_CHECK_MODULES(CURSOR, xfixes)
196
197dnl ---------------------------------------------------------------------------
198dnl - xsettings
199dnl ---------------------------------------------------------------------------
200
201PKG_CHECK_MODULES(XSETTINGS, fontconfig)
202
203dnl ---------------------------------------------------------------------------
204dnl - Keyboard plugin stuff
205dnl ---------------------------------------------------------------------------
206
207AC_ARG_ENABLE(ibus,
208 AS_HELP_STRING([--disable-ibus],
209 [Disable IBus support]),
210 enable_ibus=$enableval,
211 enable_ibus=yes)
212
213if test "x$enable_ibus" = "xyes" ; then
214 IBUS_MODULE="ibus-1.0 >= $IBUS_REQUIRED_VERSION"
215 AC_DEFINE(HAVE_IBUS, 1, [Defined if IBus support is enabled])
216else
217 IBUS_MODULE=
218fi
219AM_CONDITIONAL(HAVE_IBUS, test "x$enable_ibus" == "xyes")
220
221PKG_CHECK_MODULES(KEYBOARD, xkbfile $IBUS_MODULE gnome-desktop-3.0 >= $GNOME_DESKTOP_REQUIRED_VERSION)
222
223dnl ---------------------------------------------------------------------------
224dnl - Housekeeping plugin stuff
225dnl ---------------------------------------------------------------------------
226
227PKG_CHECK_MODULES(GIOUNIX, [gio-unix-2.0])
228
229dnl ---------------------------------------------------------------------------
230dnl - media-keys plugin stuff
231dnl ---------------------------------------------------------------------------
232
233PKG_CHECK_MODULES(MEDIA_KEYS, [gio-unix-2.0 libpulse >= $PA_REQUIRED_VERSION $GUDEV_PKG libpulse-mainloop-glib >= $PA_REQUIRED_VERSION libcanberra libnotify])
234
235dnl ---------------------------------------------------------------------------
236dnl - xrandr plugin stuff
237dnl ---------------------------------------------------------------------------
238
239PKG_CHECK_MODULES(XRANDR, [gnome-desktop-3.0 >= $GNOME_DESKTOP_REQUIRED_VERSION upower-glib >= $UPOWER_REQUIRED_VERSION])
240
241dnl ---------------------------------------------------------------------------
242dnl - orientation plugin stuff
243dnl ---------------------------------------------------------------------------
244
245if test x$have_gudev != xno; then
246 PKG_CHECK_MODULES(ORIENTATION, [gnome-desktop-3.0 >= $GNOME_DESKTOP_REQUIRED_VERSION gudev-1.0])
247fi
248
249dnl ---------------------------------------------------------------------------
250dnl - sound plugin stuff
251dnl ---------------------------------------------------------------------------
252
253PKG_CHECK_MODULES(SOUND, [libpulse >= $PA_REQUIRED_VERSION $GUDEV_PKG libpulse-mainloop-glib >= $PA_REQUIRED_VERSION])
254
255# ---------------------------------------------------------------------------
256# Power
257# ---------------------------------------------------------------------------
258PKG_CHECK_MODULES(POWER, upower-glib >= $UPOWER_REQUIRED_VERSION gnome-desktop-3.0 >= $GNOME_DESKTOP_REQUIRED_VERSION libcanberra-gtk3 libnotify x11 xext)
259
260if test x$have_gudev != xno; then
261 PKG_CHECK_MODULES(BACKLIGHT_HELPER,
262 glib-2.0 >= $GLIB_REQUIRED_VERSION
263 gudev-1.0
264 )
265fi
266
267dnl ---------------------------------------------------------------------------
268dnl - color
269dnl ---------------------------------------------------------------------------
270
271PKG_CHECK_MODULES(COLOR, [colord >= 0.1.9 gnome-desktop-3.0 >= $GNOME_DESKTOP_REQUIRED_VERSION libcanberra-gtk3])
272
273dnl ---------------------------------------------------------------------------
274dnl - wacom (disabled for s390/s390x and non Linux platforms)
275dnl ---------------------------------------------------------------------------
276
277case $host_os in
278 linux*)
279 if test "$host_cpu" = s390 -o "$host_cpu" = s390x; then
280 have_wacom=no
281 else
282 if test x$enable_gudev != xno; then
283 PKG_CHECK_MODULES(WACOM, [libwacom >= $LIBWACOM_REQUIRED_VERSION x11 xi xtst gudev-1.0 gnome-desktop-3.0 >= $GNOME_DESKTOP_REQUIRED_VERSION xorg-wacom])
284 else
285 AC_MSG_ERROR([GUdev is necessary to compile Wacom support])
286 fi
287 have_wacom=yes
288 fi
289 ;;
290 *)
291 have_wacom=no
292 ;;
293esac
294AM_CONDITIONAL(HAVE_WACOM, test x$have_wacom = xyes)
295
296dnl ==============================================
297dnl PackageKit section
298dnl ==============================================
299
300have_packagekit=false
301AC_ARG_ENABLE(packagekit,
302 AC_HELP_STRING([--disable-packagekit],
303 [turn off PackageKit support]),
304 [case "${enableval}" in
305 yes) WANT_PACKAGEKIT=yes ;;
306 no) WANT_PACKAGEKIT=no ;;
307 *) AC_MSG_ERROR(bad value ${enableval} for --disable-packagekit) ;;
308 esac],
309 [WANT_PACKAGEKIT=yes]) dnl Default value
310
311if test x$WANT_PACKAGEKIT = xyes ; then
312 PK_REQUIRED_VERSION=0.7.4
313 PKG_CHECK_MODULES(PACKAGEKIT, glib-2.0 packagekit-glib2 >= $PK_REQUIRED_VERSION upower-glib >= $UPOWER_REQUIRED_VERSION gudev-1.0 libnotify >= $LIBNOTIFY_REQUIRED_VERSION,
314 [have_packagekit=true
315 AC_DEFINE(HAVE_PACKAGEKIT, 1, [Define if PackageKit should be used])],
316 [have_packagekit=false])
317fi
318AM_CONDITIONAL(HAVE_PACKAGEKIT, test "x$have_packagekit" = "xtrue")
319
320AC_SUBST(PACKAGEKIT_CFLAGS)
321AC_SUBST(PACKAGEKIT_LIBS)
322
323dnl ==============================================
324dnl smartcard section
325dnl ==============================================
326have_smartcard_support=false
327AC_ARG_ENABLE(smartcard-support,
328 AC_HELP_STRING([--disable-smartcard-support],
329 [turn off smartcard support]),
330 [case "${enableval}" in
331 yes) WANT_SMARTCARD_SUPPORT=yes ;;
332 no) WANT_SMARTCARD_SUPPORT=no ;;
333 *) AC_MSG_ERROR(bad value ${enableval} for --disable-smartcard-support) ;;
334 esac],
335 [WANT_SMARTCARD_SUPPORT=yes])
336
337if test x$WANT_SMARTCARD_SUPPORT = xyes ; then
338 NSS_REQUIRED_VERSION=3.11.2
339 PKG_CHECK_MODULES(NSS, nss >= $NSS_REQUIRED_VERSION,
340 [have_smartcard_support=true
341 AC_DEFINE(SMARTCARD_SUPPORT, 1, [Define if smartcard support should be enabled])],
342 [have_smartcard_support=false])
343fi
344AM_CONDITIONAL(SMARTCARD_SUPPORT, test "x$have_smartcard_support" = "xtrue")
345
346AC_SUBST(NSS_CFLAGS)
347AC_SUBST(NSS_LIBS)
348
349AC_ARG_WITH(nssdb,
350 AC_HELP_STRING([--with-nssdb],
351 [where system NSS database is]))
352
353NSS_DATABASE=""
354if test "x$have_smartcard_support" = "xtrue"; then
355 if ! test -z "$with_nssdb" ; then
356 NSS_DATABASE="$with_nssdb"
357 else
358 NSS_DATABASE="${sysconfdir}/pki/nssdb"
359 fi
360else
361 if ! test -z "$with_nssdb" ; then
362 AC_MSG_WARN([nssdb specified when smartcard support is disabled])
363 fi
364fi
365
366AC_SUBST(NSS_DATABASE)
367
368
369dnl ==============================================
370dnl systemd check
371dnl ==============================================
372
373AC_ARG_ENABLE([systemd],
374 AS_HELP_STRING([--enable-systemd], [Use systemd for session tracking]),
375 [with_systemd=$enableval],
376 [with_systemd=no])
377if test "$with_systemd" = "yes" ; then
378 PKG_CHECK_MODULES(SYSTEMD, [libsystemd-login])
379 AC_DEFINE(HAVE_SYSTEMD, 1, [Define if systemd is used for session tracking])
380 SESSION_TRACKING=systemd
381else
382 SESSION_TRACKING=ConsoleKit
383fi
384
385AC_SUBST(SYSTEMD_CFLAGS)
386AC_SUBST(SYSTEMD_LIBS)
387
388AM_CONDITIONAL(WITH_SYSTEMD, [test "$with_systemd" = "yes"], [Using systemd])
389
390# ---------------------------------------------------------------------------
391# CUPS
392# ---------------------------------------------------------------------------
393
394AC_ARG_ENABLE(cups,
395 AS_HELP_STRING([--disable-cups], [disable CUPS support (default: enabled)]),,
396 enable_cups=yes)
397
398if test x"$enable_cups" != x"no" ; then
399 AC_PROG_SED
400
401 AC_PATH_PROG(CUPS_CONFIG, cups-config)
402
403 if test x$CUPS_CONFIG = x; then
404 AC_MSG_ERROR([cups-config not found but CUPS support requested])
405 fi
406
407 CUPS_API_VERSION=`$CUPS_CONFIG --api-version`
408 CUPS_API_MAJOR=`echo $ECHO_N $CUPS_API_VERSION | cut -d . -f 1`
409 CUPS_API_MINOR=`echo $ECHO_N $CUPS_API_VERSION | cut -d . -f 2`
410
411 AC_CHECK_HEADERS([cups/cups.h cups/http.h cups/ipp.h],,
412 AC_MSG_ERROR([CUPS headers not found but CUPS support requested]))
413
414 if ! test $CUPS_API_MAJOR -gt 1 -o \
415 $CUPS_API_MAJOR -eq 1 -a $CUPS_API_MINOR -ge 4 ; then
416 AC_MSG_ERROR([CUPS 1.4 or newer not found, but CUPS support requested])
417 fi
418
419 CUPS_CFLAGS=`$CUPS_CONFIG --cflags | $SED -e 's/-O\w*//g' -e 's/-m\w*//g'`
420 CUPS_LIBS=`$CUPS_CONFIG --libs`
421 AC_SUBST(CUPS_CFLAGS)
422 AC_SUBST(CUPS_LIBS)
423fi
424
425AM_CONDITIONAL(BUILD_PRINT_NOTIFICATIONS, [test x"$enable_cups" = x"yes"])
426
427# ---------------------------------------------------------------------------
428# Enable Profiling
429# ---------------------------------------------------------------------------
430AC_ARG_ENABLE(profiling,
431 [AC_HELP_STRING([--enable-profiling],
432 [turn on profiling])],
433 , enable_profiling=no)
434if test "x$enable_profiling" = "xyes"; then
435 AC_DEFINE(ENABLE_PROFILING,1,[enable profiling])
436fi
437
438
439# ---------------------------------------------------------------------------
440# Plugins
441# ---------------------------------------------------------------------------
442
443plugindir='$(libdir)/gnome-settings-daemon-gsd_api_version'
444AC_SUBST([plugindir])
445
446PLUGIN_CFLAGS="-DG_LOG_DOMAIN=\"\\\"\$(plugin_name)-plugin\\\"\" -DPLUGIN_NAME=\"\\\"\$(plugin_name)\\\"\" "
447AC_SUBST(PLUGIN_CFLAGS)
448
449AC_ARG_ENABLE(man,
450 [AS_HELP_STRING([--enable-man],
451 [generate man pages [default=yes]])],,
452 enable_man=yes)
453if test "$enable_man" != no; then
454 AC_PATH_PROG([XSLTPROC], [xsltproc])
455 if test -z "$XSLTPROC"; then
456 AC_MSG_ERROR([xsltproc is required for --enable-man])
457 fi
458fi
459AM_CONDITIONAL(ENABLE_MAN, test "$enable_man" != no)
460
461dnl ---------------------------------------------------------------------------
462dnl - Finish
463dnl ---------------------------------------------------------------------------
464
465
466# Turn on the additional warnings last, so warnings don't affect other tests.
467
468AC_ARG_ENABLE(more-warnings,
469 [AC_HELP_STRING([--enable-more-warnings],
470 [Maximum compiler warnings])],
471 set_more_warnings="$enableval",[
472 if test -d $srcdir/.git; then
473 set_more_warnings=yes
474 else
475 set_more_warnings=no
476 fi
477 ])
478AC_MSG_CHECKING(for more warnings)
479if test "$GCC" = "yes" -a "$set_more_warnings" != "no"; then
480 AC_MSG_RESULT(yes)
481 CFLAGS="\
482 -Wall \
483 -Wchar-subscripts -Wmissing-declarations -Wmissing-prototypes \
484 -Wnested-externs -Wpointer-arith \
485 -Wcast-align -Wsign-compare \
486 $CFLAGS"
487
488 for option in -Wno-strict-aliasing -Wno-sign-compare; do
489 SAVE_CFLAGS="$CFLAGS"
490 CFLAGS="$CFLAGS $option"
491 AC_MSG_CHECKING([whether gcc understands $option])
492 AC_TRY_COMPILE([], [],
493 has_option=yes,
494 has_option=no,)
495 if test $has_option = no; then
496 CFLAGS="$SAVE_CFLAGS"
497 fi
498 AC_MSG_RESULT($has_option)
499 unset has_option
500 unset SAVE_CFLAGS
501 done
502 unset option
503else
504 AC_MSG_RESULT(no)
505fi
506
507#
508# Enable Debug
509#
510AC_ARG_ENABLE(debug,
511 [AC_HELP_STRING([--enable-debug],
512 [turn on debugging])],
513 , enable_debug=yes)
514if test "$enable_debug" = "yes"; then
515 DEBUG_CFLAGS="-DG_ENABLE_DEBUG"
516else
517 if test "x$enable_debug" = "xno"; then
518 DEBUG_CFLAGS="-DG_DISABLE_ASSERT -DG_DISABLE_CHECKS"
519 else
520 DEBUG_CFLAGS=""
521 fi
522fi
523AC_SUBST(DEBUG_CFLAGS)
524
525AC_OUTPUT([
526Makefile
527gnome-settings-daemon/Makefile
528plugins/Makefile
529plugins/a11y-keyboard/Makefile
530plugins/a11y-settings/Makefile
531plugins/automount/Makefile
532plugins/background/Makefile
533plugins/clipboard/Makefile
534plugins/color/Makefile
535plugins/common/Makefile
536plugins/cursor/Makefile
537plugins/dummy/Makefile
538plugins/power/Makefile
539plugins/housekeeping/Makefile
540plugins/keyboard/Makefile
541plugins/media-keys/Makefile
542plugins/media-keys/cut-n-paste/Makefile
543plugins/mouse/Makefile
544plugins/orientation/Makefile
545plugins/print-notifications/Makefile
546plugins/screensaver-proxy/Makefile
547plugins/smartcard/Makefile
548plugins/sound/Makefile
549plugins/updates/Makefile
550plugins/wacom/Makefile
551plugins/xrandr/Makefile
552plugins/xsettings/Makefile
553data/Makefile
554data/gnome-settings-daemon.pc
555data/gnome-settings-daemon-uninstalled.pc
556data/org.gnome.settings-daemon.plugins.gschema.xml.in
557data/org.gnome.settings-daemon.plugins.xsettings.gschema.xml.in
558data/org.gnome.settings-daemon.plugins.keyboard.gschema.xml.in
559data/org.gnome.settings-daemon.plugins.power.gschema.xml.in
560data/org.gnome.settings-daemon.plugins.color.gschema.xml.in
561data/org.gnome.settings-daemon.plugins.media-keys.gschema.xml.in
562data/org.gnome.settings-daemon.peripherals.gschema.xml.in
563data/org.gnome.settings-daemon.plugins.housekeeping.gschema.xml.in
564data/org.gnome.settings-daemon.plugins.orientation.gschema.xml.in
565data/org.gnome.settings-daemon.plugins.updates.gschema.xml.in
566data/org.gnome.settings-daemon.plugins.xrandr.gschema.xml.in
567data/org.gnome.settings-daemon.peripherals.wacom.gschema.xml.in
568data/org.gnome.settings-daemon.plugins.print-notifications.gschema.xml.in
569po/Makefile.in
570man/Makefile
571])
572
573dnl ---------------------------------------------------------------------------
574dnl - Show summary
575dnl ---------------------------------------------------------------------------
576
577echo "
578 gnome-settings-daemon $VERSION
579 =============================
580
581 prefix: ${prefix}
582 exec_prefix: ${exec_prefix}
583 libdir: ${libdir}
584 bindir: ${bindir}
585 sbindir: ${sbindir}
586 sysconfdir: ${sysconfdir}
587 sysconfsubdir: ${sysconfsubdir}
588 localstatedir: ${localstatedir}
589 plugindir: ${plugindir}
590 datadir: ${datadir}
591 source code location: ${srcdir}
592 compiler: ${CC}
593 cflags: ${CFLAGS}
594 Maintainer mode: ${USE_MAINTAINER_MODE}
595
596 Session tracking: ${SESSION_TRACKING}
597 LCMS DICT support: ${have_new_lcms}
598 IBus support: ${enable_ibus}
599 Libnotify support: ${have_libnotify}
600 App indicator support: ${enable_appindicator}
601 PackageKit support: ${have_packagekit}
602 Smartcard support: ${have_smartcard_support}
603 Cups support: ${enable_cups}
604 Wacom support: ${have_wacom}
605${NSS_DATABASE:+\
606 System nssdb: ${NSS_DATABASE}
607}\
608 Profiling support: ${enable_profiling}
609"
6100
=== removed directory '.pc/sync_input_sources_to_accountsservice.patch/plugins'
=== removed directory '.pc/sync_input_sources_to_accountsservice.patch/plugins/keyboard'
=== removed file '.pc/sync_input_sources_to_accountsservice.patch/plugins/keyboard/gsd-keyboard-manager.c'
--- .pc/sync_input_sources_to_accountsservice.patch/plugins/keyboard/gsd-keyboard-manager.c 2013-08-29 16:10:41 +0000
+++ .pc/sync_input_sources_to_accountsservice.patch/plugins/keyboard/gsd-keyboard-manager.c 1970-01-01 00:00:00 +0000
@@ -1,1708 +0,0 @@
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 * Written by Sergey V. Oudaltsov <svu@users.sourceforge.net>
6 *
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 2 of the License, or
10 * (at your option) any later version.
11 *
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, write to the Free Software
19 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
20 *
21 */
22
23#include "config.h"
24
25#include <sys/types.h>
26#include <sys/wait.h>
27#include <stdlib.h>
28#include <stdio.h>
29#include <unistd.h>
30#include <string.h>
31#include <errno.h>
32
33#include <locale.h>
34
35#include <glib.h>
36#include <glib/gi18n.h>
37#include <gdk/gdk.h>
38#include <gdk/gdkx.h>
39#include <gtk/gtk.h>
40
41#include <X11/XKBlib.h>
42#include <X11/keysym.h>
43#include <X11/extensions/XKBrules.h>
44
45#define GNOME_DESKTOP_USE_UNSTABLE_API
46#include <libgnome-desktop/gnome-xkb-info.h>
47
48#ifdef HAVE_IBUS
49#include <ibus.h>
50#endif
51
52#include "gnome-settings-profile.h"
53#include "gsd-keyboard-manager.h"
54#include "gsd-input-helper.h"
55#include "gsd-enums.h"
56
57#define GSD_KEYBOARD_MANAGER_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), GSD_TYPE_KEYBOARD_MANAGER, GsdKeyboardManagerPrivate))
58
59#define GSD_KEYBOARD_DIR "org.gnome.settings-daemon.peripherals.keyboard"
60
61#define KEY_REPEAT "repeat"
62#define KEY_CLICK "click"
63#define KEY_INTERVAL "repeat-interval"
64#define KEY_DELAY "delay"
65#define KEY_CLICK_VOLUME "click-volume"
66#define KEY_REMEMBER_NUMLOCK_STATE "remember-numlock-state"
67#define KEY_NUMLOCK_STATE "numlock-state"
68
69#define KEY_BELL_VOLUME "bell-volume"
70#define KEY_BELL_PITCH "bell-pitch"
71#define KEY_BELL_DURATION "bell-duration"
72#define KEY_BELL_MODE "bell-mode"
73
74#define KEY_SWITCHER "input-sources-switcher"
75
76#define GNOME_DESKTOP_INTERFACE_DIR "org.gnome.desktop.interface"
77
78#define KEY_GTK_IM_MODULE "gtk-im-module"
79#define GTK_IM_MODULE_SIMPLE "gtk-im-context-simple"
80#define GTK_IM_MODULE_IBUS "ibus"
81
82#define GNOME_DESKTOP_INPUT_SOURCES_DIR "org.gnome.desktop.input-sources"
83
84#define KEY_CURRENT_INPUT_SOURCE "current"
85#define KEY_INPUT_SOURCES "sources"
86#define KEY_KEYBOARD_OPTIONS "xkb-options"
87
88#define INPUT_SOURCE_TYPE_XKB "xkb"
89#define INPUT_SOURCE_TYPE_IBUS "ibus"
90
91#define DEFAULT_LANGUAGE "en_US"
92
93struct GsdKeyboardManagerPrivate
94{
95 guint start_idle_id;
96 GSettings *settings;
97 GSettings *input_sources_settings;
98 GSettings *interface_settings;
99 GnomeXkbInfo *xkb_info;
100#ifdef HAVE_IBUS
101 IBusBus *ibus;
102 GHashTable *ibus_engines;
103 GHashTable *ibus_xkb_engines;
104 GCancellable *ibus_cancellable;
105 gboolean session_is_fallback;
106#endif
107 gint xkb_event_base;
108 GsdNumLockState old_state;
109 GdkDeviceManager *device_manager;
110 guint device_added_id;
111 guint device_removed_id;
112
113 gboolean input_sources_switcher_spawned;
114 GPid input_sources_switcher_pid;
115};
116
117static void gsd_keyboard_manager_class_init (GsdKeyboardManagerClass *klass);
118static void gsd_keyboard_manager_init (GsdKeyboardManager *keyboard_manager);
119static void gsd_keyboard_manager_finalize (GObject *object);
120static gboolean apply_input_sources_settings (GSettings *settings,
121 gpointer keys,
122 gint n_keys,
123 GsdKeyboardManager *manager);
124static void set_gtk_im_module (GsdKeyboardManager *manager,
125 const gchar *new_module);
126
127G_DEFINE_TYPE (GsdKeyboardManager, gsd_keyboard_manager, G_TYPE_OBJECT)
128
129static gpointer manager_object = NULL;
130
131static void
132init_builder_with_sources (GVariantBuilder *builder,
133 GSettings *settings)
134{
135 const gchar *type;
136 const gchar *id;
137 GVariantIter iter;
138 GVariant *sources;
139
140 sources = g_settings_get_value (settings, KEY_INPUT_SOURCES);
141
142 g_variant_builder_init (builder, G_VARIANT_TYPE ("a(ss)"));
143
144 g_variant_iter_init (&iter, sources);
145 while (g_variant_iter_next (&iter, "(&s&s)", &type, &id))
146 g_variant_builder_add (builder, "(ss)", type, id);
147
148 g_variant_unref (sources);
149}
150
151static gboolean
152schema_is_installed (const gchar *name)
153{
154 const gchar * const *schemas;
155 const gchar * const *s;
156
157 schemas = g_settings_list_schemas ();
158 for (s = schemas; *s; ++s)
159 if (g_str_equal (*s, name))
160 return TRUE;
161
162 return FALSE;
163}
164
165#ifdef HAVE_IBUS
166static void
167clear_ibus (GsdKeyboardManager *manager)
168{
169 GsdKeyboardManagerPrivate *priv = manager->priv;
170
171 g_cancellable_cancel (priv->ibus_cancellable);
172 g_clear_object (&priv->ibus_cancellable);
173 g_clear_pointer (&priv->ibus_engines, g_hash_table_destroy);
174 g_clear_pointer (&priv->ibus_xkb_engines, g_hash_table_destroy);
175 g_clear_object (&priv->ibus);
176}
177
178static gchar *
179make_xkb_source_id (const gchar *engine_id)
180{
181 gchar *id;
182 gchar *p;
183 gint n_colons = 0;
184
185 /* engine_id is like "xkb:layout:variant:lang" where
186 * 'variant' and 'lang' might be empty */
187
188 engine_id += 4;
189
190 for (p = (gchar *)engine_id; *p; ++p)
191 if (*p == ':')
192 if (++n_colons == 2)
193 break;
194 if (!*p)
195 return NULL;
196
197 id = g_strndup (engine_id, p - engine_id + 1);
198
199 id[p - engine_id] = '\0';
200
201 /* id is "layout:variant" where 'variant' might be empty */
202
203 for (p = id; *p; ++p)
204 if (*p == ':') {
205 if (*(p + 1) == '\0')
206 *p = '\0';
207 else
208 *p = '+';
209 break;
210 }
211
212 /* id is "layout+variant" or "layout" */
213
214 return id;
215}
216
217static void
218fetch_ibus_engines_result (GObject *object,
219 GAsyncResult *result,
220 GsdKeyboardManager *manager)
221{
222 GsdKeyboardManagerPrivate *priv = manager->priv;
223 GList *list, *l;
224 GError *error = NULL;
225
226 /* engines shouldn't be there yet */
227 g_return_if_fail (priv->ibus_engines == NULL);
228
229 g_clear_object (&priv->ibus_cancellable);
230
231 list = ibus_bus_list_engines_async_finish (priv->ibus,
232 result,
233 &error);
234 if (!list && error) {
235 if (!g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED))
236 g_warning ("Couldn't finish IBus request: %s", error->message);
237 g_error_free (error);
238
239 clear_ibus (manager);
240 return;
241 }
242
243 /* Maps IBus engine ids to engine description objects */
244 priv->ibus_engines = g_hash_table_new_full (g_str_hash, g_str_equal, NULL, g_object_unref);
245 /* Maps XKB source id strings to engine description objects */
246 priv->ibus_xkb_engines = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL);
247
248 for (l = list; l; l = l->next) {
249 IBusEngineDesc *engine = l->data;
250 const gchar *engine_id = ibus_engine_desc_get_name (engine);
251
252 g_hash_table_replace (priv->ibus_engines, (gpointer)engine_id, engine);
253
254 if (strncmp ("xkb:", engine_id, 4) == 0) {
255 gchar *xkb_source_id = make_xkb_source_id (engine_id);
256 if (xkb_source_id)
257 g_hash_table_replace (priv->ibus_xkb_engines,
258 xkb_source_id,
259 engine);
260 }
261 }
262 g_list_free (list);
263
264 apply_input_sources_settings (priv->input_sources_settings, NULL, 0, manager);
265}
266
267static void
268fetch_ibus_engines (GsdKeyboardManager *manager)
269{
270 GsdKeyboardManagerPrivate *priv = manager->priv;
271
272 /* engines shouldn't be there yet */
273 g_return_if_fail (priv->ibus_engines == NULL);
274 g_return_if_fail (priv->ibus_cancellable == NULL);
275
276 priv->ibus_cancellable = g_cancellable_new ();
277
278 ibus_bus_list_engines_async (priv->ibus,
279 -1,
280 priv->ibus_cancellable,
281 (GAsyncReadyCallback)fetch_ibus_engines_result,
282 manager);
283}
284
285static void
286maybe_start_ibus (GsdKeyboardManager *manager,
287 GVariant *sources)
288{
289 gboolean need_ibus = FALSE;
290 GVariantIter iter;
291 const gchar *type;
292
293 if (manager->priv->session_is_fallback)
294 return;
295
296 g_variant_iter_init (&iter, sources);
297 while (g_variant_iter_next (&iter, "(&s&s)", &type, NULL))
298 if (g_str_equal (type, INPUT_SOURCE_TYPE_IBUS)) {
299 need_ibus = TRUE;
300 break;
301 }
302
303 if (!need_ibus)
304 return;
305
306 if (!manager->priv->ibus) {
307 ibus_init ();
308 manager->priv->ibus = ibus_bus_new_async ();
309 g_signal_connect_swapped (manager->priv->ibus, "connected",
310 G_CALLBACK (fetch_ibus_engines), manager);
311 g_signal_connect_swapped (manager->priv->ibus, "disconnected",
312 G_CALLBACK (clear_ibus), manager);
313 }
314 /* IBus doesn't export API in the session bus. The only thing
315 * we have there is a well known name which we can use as a
316 * sure-fire way to activate it. */
317 g_bus_unwatch_name (g_bus_watch_name (G_BUS_TYPE_SESSION,
318 IBUS_SERVICE_IBUS,
319 G_BUS_NAME_WATCHER_FLAGS_AUTO_START,
320 NULL,
321 NULL,
322 NULL,
323 NULL));
324}
325
326static void
327got_session_name (GObject *object,
328 GAsyncResult *res,
329 GsdKeyboardManager *manager)
330{
331 GVariant *result, *variant;
332 GDBusConnection *connection = G_DBUS_CONNECTION (object);
333 GsdKeyboardManagerPrivate *priv = manager->priv;
334 const gchar *session_name = NULL;
335 GError *error = NULL;
336
337 /* IBus shouldn't have been touched yet */
338 g_return_if_fail (priv->ibus == NULL);
339
340 g_clear_object (&priv->ibus_cancellable);
341
342 result = g_dbus_connection_call_finish (connection, res, &error);
343 if (!result) {
344 g_warning ("Couldn't get session name: %s", error->message);
345 g_error_free (error);
346 goto out;
347 }
348
349 g_variant_get (result, "(v)", &variant);
350 g_variant_unref (result);
351
352 g_variant_get (variant, "&s", &session_name);
353
354 if (g_strcmp0 (session_name, "gnome") == 0 || g_strcmp0 (session_name, "ubuntu") == 0)
355 manager->priv->session_is_fallback = FALSE;
356
357 g_variant_unref (variant);
358 out:
359 apply_input_sources_settings (manager->priv->input_sources_settings, NULL, 0, manager);
360 g_object_unref (connection);
361}
362
363static void
364got_bus (GObject *object,
365 GAsyncResult *res,
366 GsdKeyboardManager *manager)
367{
368 GDBusConnection *connection;
369 GsdKeyboardManagerPrivate *priv = manager->priv;
370 GError *error = NULL;
371
372 /* IBus shouldn't have been touched yet */
373 g_return_if_fail (priv->ibus == NULL);
374
375 g_clear_object (&priv->ibus_cancellable);
376
377 connection = g_bus_get_finish (res, &error);
378 if (!connection) {
379 g_warning ("Couldn't get session bus: %s", error->message);
380 g_error_free (error);
381 apply_input_sources_settings (priv->input_sources_settings, NULL, 0, manager);
382 return;
383 }
384
385 priv->ibus_cancellable = g_cancellable_new ();
386
387 g_dbus_connection_call (connection,
388 "org.gnome.SessionManager",
389 "/org/gnome/SessionManager",
390 "org.freedesktop.DBus.Properties",
391 "Get",
392 g_variant_new ("(ss)",
393 "org.gnome.SessionManager",
394 "SessionName"),
395 NULL,
396 G_DBUS_CALL_FLAGS_NONE,
397 -1,
398 priv->ibus_cancellable,
399 (GAsyncReadyCallback)got_session_name,
400 manager);
401}
402
403static void
404set_ibus_engine_finish (GObject *object,
405 GAsyncResult *res,
406 GsdKeyboardManager *manager)
407{
408 gboolean result;
409 IBusBus *ibus = IBUS_BUS (object);
410 GsdKeyboardManagerPrivate *priv = manager->priv;
411 GError *error = NULL;
412
413 g_clear_object (&priv->ibus_cancellable);
414
415 result = ibus_bus_set_global_engine_async_finish (ibus, res, &error);
416 if (!result) {
417 if (!g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED))
418 g_warning ("Couldn't set IBus engine: %s", error->message);
419 g_error_free (error);
420 }
421}
422
423static void
424set_ibus_engine (GsdKeyboardManager *manager,
425 const gchar *engine_id)
426{
427 GsdKeyboardManagerPrivate *priv = manager->priv;
428
429 g_return_if_fail (priv->ibus != NULL);
430 g_return_if_fail (priv->ibus_engines != NULL);
431
432 g_cancellable_cancel (priv->ibus_cancellable);
433 g_clear_object (&priv->ibus_cancellable);
434 priv->ibus_cancellable = g_cancellable_new ();
435
436 ibus_bus_set_global_engine_async (priv->ibus,
437 engine_id,
438 -1,
439 priv->ibus_cancellable,
440 (GAsyncReadyCallback)set_ibus_engine_finish,
441 manager);
442}
443
444static void
445set_ibus_xkb_engine (GsdKeyboardManager *manager,
446 const gchar *xkb_id)
447{
448 IBusEngineDesc *engine;
449 GsdKeyboardManagerPrivate *priv = manager->priv;
450
451 if (!priv->ibus_xkb_engines)
452 return;
453
454 engine = g_hash_table_lookup (priv->ibus_xkb_engines, xkb_id);
455 if (!engine)
456 return;
457
458 set_ibus_engine (manager, ibus_engine_desc_get_name (engine));
459}
460
461/* XXX: See upstream bug:
462 * https://codereview.appspot.com/6586075/ */
463static gchar *
464layout_from_ibus_layout (const gchar *ibus_layout)
465{
466 const gchar *p;
467
468 /* we get something like "layout(variant)[option1,option2]" */
469
470 p = ibus_layout;
471 while (*p) {
472 if (*p == '(' || *p == '[')
473 break;
474 p += 1;
475 }
476
477 return g_strndup (ibus_layout, p - ibus_layout);
478}
479
480static gchar *
481variant_from_ibus_layout (const gchar *ibus_layout)
482{
483 const gchar *a, *b;
484
485 /* we get something like "layout(variant)[option1,option2]" */
486
487 a = ibus_layout;
488 while (*a) {
489 if (*a == '(')
490 break;
491 a += 1;
492 }
493 if (!*a)
494 return NULL;
495
496 a += 1;
497 b = a;
498 while (*b) {
499 if (*b == ')')
500 break;
501 b += 1;
502 }
503 if (!*b)
504 return NULL;
505
506 return g_strndup (a, b - a);
507}
508
509static gchar **
510options_from_ibus_layout (const gchar *ibus_layout)
511{
512 const gchar *a, *b;
513 GPtrArray *opt_array;
514
515 /* we get something like "layout(variant)[option1,option2]" */
516
517 a = ibus_layout;
518 while (*a) {
519 if (*a == '[')
520 break;
521 a += 1;
522 }
523 if (!*a)
524 return NULL;
525
526 opt_array = g_ptr_array_new ();
527
528 do {
529 a += 1;
530 b = a;
531 while (*b) {
532 if (*b == ',' || *b == ']')
533 break;
534 b += 1;
535 }
536 if (!*b)
537 goto out;
538
539 g_ptr_array_add (opt_array, g_strndup (a, b - a));
540
541 a = b;
542 } while (*a && *a == ',');
543
544out:
545 g_ptr_array_add (opt_array, NULL);
546 return (gchar **) g_ptr_array_free (opt_array, FALSE);
547}
548
549static const gchar *
550engine_from_locale (void)
551{
552 const gchar *locale;
553 const gchar *locale_engine[][2] = {
554 { "as_IN", "m17n:as:phonetic" },
555 { "bn_IN", "m17n:bn:inscript" },
556 { "gu_IN", "m17n:gu:inscript" },
557 { "hi_IN", "m17n:hi:inscript" },
558 { "ja_JP", "anthy" },
559 { "kn_IN", "m17n:kn:kgp" },
560 { "ko_KR", "hangul" },
561 { "mai_IN", "m17n:mai:inscript" },
562 { "ml_IN", "m17n:ml:inscript" },
563 { "mr_IN", "m17n:mr:inscript" },
564 { "or_IN", "m17n:or:inscript" },
565 { "pa_IN", "m17n:pa:inscript" },
566 { "sd_IN", "m17n:sd:inscript" },
567 { "ta_IN", "m17n:ta:tamil99" },
568 { "te_IN", "m17n:te:inscript" },
569 { "zh_CN", "pinyin" },
570 { "zh_HK", "cangjie3" },
571 { "zh_TW", "chewing" },
572 };
573 gint i;
574
575 locale = setlocale (LC_CTYPE, NULL);
576 if (!locale)
577 return NULL;
578
579 for (i = 0; i < G_N_ELEMENTS (locale_engine); ++i)
580 if (g_str_has_prefix (locale, locale_engine[i][0]))
581 return locale_engine[i][1];
582
583 return NULL;
584}
585
586static void
587add_ibus_sources_from_locale (GSettings *settings)
588{
589 const gchar *locale_engine;
590 GVariantBuilder builder;
591
592 locale_engine = engine_from_locale ();
593 if (!locale_engine)
594 return;
595
596 init_builder_with_sources (&builder, settings);
597 g_variant_builder_add (&builder, "(ss)", INPUT_SOURCE_TYPE_IBUS, locale_engine);
598 g_settings_set_value (settings, KEY_INPUT_SOURCES, g_variant_builder_end (&builder));
599}
600
601static void
602convert_ibus (GSettings *settings)
603{
604 GVariantBuilder builder;
605 GSettings *ibus_settings;
606 gchar **engines, **e;
607
608 if (!schema_is_installed ("org.freedesktop.ibus.general"))
609 return;
610
611 init_builder_with_sources (&builder, settings);
612
613 ibus_settings = g_settings_new ("org.freedesktop.ibus.general");
614 engines = g_settings_get_strv (ibus_settings, "preload-engines");
615 for (e = engines; *e; ++e) {
616 if (g_str_has_prefix (*e, "xkb:"))
617 continue;
618 g_variant_builder_add (&builder, "(ss)", INPUT_SOURCE_TYPE_IBUS, *e);
619 }
620
621 g_settings_set_value (settings, KEY_INPUT_SOURCES, g_variant_builder_end (&builder));
622
623 g_strfreev (engines);
624 g_object_unref (ibus_settings);
625}
626#endif /* HAVE_IBUS */
627
628static gboolean
629xkb_set_keyboard_autorepeat_rate (guint delay, guint interval)
630{
631 return XkbSetAutoRepeatRate (GDK_DISPLAY_XDISPLAY (gdk_display_get_default ()),
632 XkbUseCoreKbd,
633 delay,
634 interval);
635}
636
637static gboolean
638check_xkb_extension (GsdKeyboardManager *manager)
639{
640 Display *dpy = GDK_DISPLAY_XDISPLAY (gdk_display_get_default ());
641 int opcode, error_base, major, minor;
642 gboolean have_xkb;
643
644 have_xkb = XkbQueryExtension (dpy,
645 &opcode,
646 &manager->priv->xkb_event_base,
647 &error_base,
648 &major,
649 &minor);
650 return have_xkb;
651}
652
653static void
654xkb_init (GsdKeyboardManager *manager)
655{
656 Display *dpy;
657
658 dpy = GDK_DISPLAY_XDISPLAY (gdk_display_get_default ());
659 XkbSelectEventDetails (dpy,
660 XkbUseCoreKbd,
661 XkbStateNotify,
662 XkbModifierLockMask,
663 XkbModifierLockMask);
664}
665
666static unsigned
667numlock_NumLock_modifier_mask (void)
668{
669 Display *dpy = GDK_DISPLAY_XDISPLAY (gdk_display_get_default ());
670 return XkbKeysymToModifiers (dpy, XK_Num_Lock);
671}
672
673static void
674numlock_set_xkb_state (GsdNumLockState new_state)
675{
676 unsigned int num_mask;
677 Display *dpy = GDK_DISPLAY_XDISPLAY (gdk_display_get_default ());
678 if (new_state != GSD_NUM_LOCK_STATE_ON && new_state != GSD_NUM_LOCK_STATE_OFF)
679 return;
680 num_mask = numlock_NumLock_modifier_mask ();
681 XkbLockModifiers (dpy, XkbUseCoreKbd, num_mask, new_state == GSD_NUM_LOCK_STATE_ON ? num_mask : 0);
682}
683
684static const char *
685num_lock_state_to_string (GsdNumLockState numlock_state)
686{
687 switch (numlock_state) {
688 case GSD_NUM_LOCK_STATE_UNKNOWN:
689 return "GSD_NUM_LOCK_STATE_UNKNOWN";
690 case GSD_NUM_LOCK_STATE_ON:
691 return "GSD_NUM_LOCK_STATE_ON";
692 case GSD_NUM_LOCK_STATE_OFF:
693 return "GSD_NUM_LOCK_STATE_OFF";
694 default:
695 return "UNKNOWN";
696 }
697}
698
699static GdkFilterReturn
700xkb_events_filter (GdkXEvent *xev_,
701 GdkEvent *gdkev_,
702 gpointer user_data)
703{
704 XEvent *xev = (XEvent *) xev_;
705 XkbEvent *xkbev = (XkbEvent *) xev;
706 GsdKeyboardManager *manager = (GsdKeyboardManager *) user_data;
707
708 if (xev->type != manager->priv->xkb_event_base ||
709 xkbev->any.xkb_type != XkbStateNotify)
710 return GDK_FILTER_CONTINUE;
711
712 if (xkbev->state.changed & XkbModifierLockMask) {
713 unsigned num_mask = numlock_NumLock_modifier_mask ();
714 unsigned locked_mods = xkbev->state.locked_mods;
715 GsdNumLockState numlock_state;
716
717 numlock_state = (num_mask & locked_mods) ? GSD_NUM_LOCK_STATE_ON : GSD_NUM_LOCK_STATE_OFF;
718
719 if (numlock_state != manager->priv->old_state) {
720 g_debug ("New num-lock state '%s' != Old num-lock state '%s'",
721 num_lock_state_to_string (numlock_state),
722 num_lock_state_to_string (manager->priv->old_state));
723 g_settings_set_enum (manager->priv->settings,
724 KEY_NUMLOCK_STATE,
725 numlock_state);
726 manager->priv->old_state = numlock_state;
727 }
728 }
729
730 return GDK_FILTER_CONTINUE;
731}
732
733static void
734install_xkb_filter (GsdKeyboardManager *manager)
735{
736 gdk_window_add_filter (NULL,
737 xkb_events_filter,
738 manager);
739}
740
741static void
742remove_xkb_filter (GsdKeyboardManager *manager)
743{
744 gdk_window_remove_filter (NULL,
745 xkb_events_filter,
746 manager);
747}
748
749static void
750free_xkb_component_names (XkbComponentNamesRec *p)
751{
752 g_return_if_fail (p != NULL);
753
754 free (p->keymap);
755 free (p->keycodes);
756 free (p->types);
757 free (p->compat);
758 free (p->symbols);
759 free (p->geometry);
760
761 g_free (p);
762}
763
764static void
765upload_xkb_description (const gchar *rules_file_path,
766 XkbRF_VarDefsRec *var_defs,
767 XkbComponentNamesRec *comp_names)
768{
769 Display *display = GDK_DISPLAY_XDISPLAY (gdk_display_get_default ());
770 XkbDescRec *xkb_desc;
771 gchar *rules_file;
772
773 /* Upload it to the X server using the same method as setxkbmap */
774 xkb_desc = XkbGetKeyboardByName (display,
775 XkbUseCoreKbd,
776 comp_names,
777 XkbGBN_AllComponentsMask,
778 XkbGBN_AllComponentsMask &
779 (~XkbGBN_GeometryMask), True);
780 if (!xkb_desc) {
781 g_warning ("Couldn't upload new XKB keyboard description");
782 return;
783 }
784
785 XkbFreeKeyboard (xkb_desc, 0, True);
786
787 rules_file = g_path_get_basename (rules_file_path);
788
789 if (!XkbRF_SetNamesProp (display, rules_file, var_defs))
790 g_warning ("Couldn't update the XKB root window property");
791
792 g_free (rules_file);
793}
794
795static gchar *
796language_code_from_locale (const gchar *locale)
797{
798 if (!locale || !locale[0] || !locale[1])
799 return NULL;
800
801 if (!locale[2] || locale[2] == '_' || locale[2] == '.')
802 return g_strndup (locale, 2);
803
804 if (!locale[3] || locale[3] == '_' || locale[3] == '.')
805 return g_strndup (locale, 3);
806
807 return NULL;
808}
809
810static gchar *
811build_xkb_group_string (const gchar *user,
812 const gchar *locale,
813 const gchar *latin)
814{
815 gchar *string;
816 gsize length = 0;
817 guint commas = 2;
818
819 if (latin)
820 length += strlen (latin);
821 else
822 commas -= 1;
823
824 if (locale)
825 length += strlen (locale);
826 else
827 commas -= 1;
828
829 length += strlen (user) + commas + 1;
830
831 string = malloc (length);
832
833 if (locale && latin)
834 sprintf (string, "%s,%s,%s", user, locale, latin);
835 else if (locale)
836 sprintf (string, "%s,%s", user, locale);
837 else if (latin)
838 sprintf (string, "%s,%s", user, latin);
839 else
840 sprintf (string, "%s", user);
841
842 return string;
843}
844
845static gboolean
846layout_equal (const gchar *layout_a,
847 const gchar *variant_a,
848 const gchar *layout_b,
849 const gchar *variant_b)
850{
851 return !g_strcmp0 (layout_a, layout_b) && !g_strcmp0 (variant_a, variant_b);
852}
853
854static void
855replace_layout_and_variant (GsdKeyboardManager *manager,
856 XkbRF_VarDefsRec *xkb_var_defs,
857 const gchar *layout,
858 const gchar *variant)
859{
860 /* Toolkits need to know about both a latin layout to handle
861 * accelerators which are usually defined like Ctrl+C and a
862 * layout with the symbols for the language used in UI strings
863 * to handle mnemonics like Alt+Ф, so we try to find and add
864 * them in XKB group slots after the layout which the user
865 * actually intends to type with. */
866 const gchar *latin_layout = "us";
867 const gchar *latin_variant = "";
868 const gchar *locale_layout = NULL;
869 const gchar *locale_variant = NULL;
870 const gchar *locale;
871 gchar *language;
872
873 if (!layout)
874 return;
875
876 if (!variant)
877 variant = "";
878
879 locale = setlocale (LC_MESSAGES, NULL);
880 /* If LANG is empty, default to en_US */
881 if (!locale)
882 language = g_strdup (DEFAULT_LANGUAGE);
883 else
884 language = language_code_from_locale (locale);
885
886 if (!language)
887 language = language_code_from_locale (DEFAULT_LANGUAGE);
888
889 gnome_xkb_info_get_layout_info_for_language (manager->priv->xkb_info,
890 language,
891 NULL,
892 NULL,
893 NULL,
894 &locale_layout,
895 &locale_variant);
896 g_free (language);
897
898 /* We want to minimize the number of XKB groups if we have
899 * duplicated layout+variant pairs.
900 *
901 * Also, if a layout doesn't have a variant we still have to
902 * include it in the variants string because the number of
903 * variants must agree with the number of layouts. For
904 * instance:
905 *
906 * layouts: "us,ru,us"
907 * variants: "dvorak,,"
908 */
909 if (layout_equal (latin_layout, latin_variant, locale_layout, locale_variant) ||
910 layout_equal (latin_layout, latin_variant, layout, variant)) {
911 latin_layout = NULL;
912 latin_variant = NULL;
913 }
914
915 if (layout_equal (locale_layout, locale_variant, layout, variant)) {
916 locale_layout = NULL;
917 locale_variant = NULL;
918 }
919
920 free (xkb_var_defs->layout);
921 xkb_var_defs->layout = build_xkb_group_string (layout, locale_layout, latin_layout);
922
923 free (xkb_var_defs->variant);
924 xkb_var_defs->variant = build_xkb_group_string (variant, locale_variant, latin_variant);
925}
926
927static gchar *
928build_xkb_options_string (gchar **options)
929{
930 gchar *string;
931
932 if (*options) {
933 gint i;
934 gsize len;
935 gchar *ptr;
936
937 /* First part, getting length */
938 len = 1 + strlen (options[0]);
939 for (i = 1; options[i] != NULL; i++)
940 len += strlen (options[i]);
941 len += (i - 1); /* commas */
942
943 /* Second part, building string */
944 string = malloc (len);
945 ptr = g_stpcpy (string, *options);
946 for (i = 1; options[i] != NULL; i++) {
947 ptr = g_stpcpy (ptr, ",");
948 ptr = g_stpcpy (ptr, options[i]);
949 }
950 } else {
951 string = malloc (1);
952 *string = '\0';
953 }
954
955 return string;
956}
957
958static gchar **
959append_options (gchar **a,
960 gchar **b)
961{
962 gchar **c, **p;
963
964 if (!a && !b)
965 return NULL;
966 else if (!a)
967 return g_strdupv (b);
968 else if (!b)
969 return g_strdupv (a);
970
971 c = g_new0 (gchar *, g_strv_length (a) + g_strv_length (b) + 1);
972 p = c;
973
974 while (*a) {
975 *p = g_strdup (*a);
976 p += 1;
977 a += 1;
978 }
979 while (*b) {
980 *p = g_strdup (*b);
981 p += 1;
982 b += 1;
983 }
984
985 return c;
986}
987
988static void
989add_xkb_options (GsdKeyboardManager *manager,
990 XkbRF_VarDefsRec *xkb_var_defs,
991 gchar **extra_options)
992{
993 gchar **options;
994 gchar **settings_options;
995
996 settings_options = g_settings_get_strv (manager->priv->input_sources_settings,
997 KEY_KEYBOARD_OPTIONS);
998 options = append_options (settings_options, extra_options);
999 g_strfreev (settings_options);
1000
1001 free (xkb_var_defs->options);
1002 xkb_var_defs->options = build_xkb_options_string (options);
1003
1004 g_strfreev (options);
1005}
1006
1007static void
1008apply_xkb_settings (GsdKeyboardManager *manager,
1009 const gchar *layout,
1010 const gchar *variant,
1011 gchar **options)
1012{
1013 XkbRF_RulesRec *xkb_rules;
1014 XkbRF_VarDefsRec *xkb_var_defs;
1015 gchar *rules_file_path;
1016
1017 gnome_xkb_info_get_var_defs (&rules_file_path, &xkb_var_defs);
1018
1019 add_xkb_options (manager, xkb_var_defs, options);
1020 replace_layout_and_variant (manager, xkb_var_defs, layout, variant);
1021
1022 gdk_error_trap_push ();
1023
1024 xkb_rules = XkbRF_Load (rules_file_path, NULL, True, True);
1025 if (xkb_rules) {
1026 XkbComponentNamesRec *xkb_comp_names;
1027 xkb_comp_names = g_new0 (XkbComponentNamesRec, 1);
1028
1029 XkbRF_GetComponents (xkb_rules, xkb_var_defs, xkb_comp_names);
1030 upload_xkb_description (rules_file_path, xkb_var_defs, xkb_comp_names);
1031
1032 free_xkb_component_names (xkb_comp_names);
1033 XkbRF_Free (xkb_rules, True);
1034 } else {
1035 g_warning ("Couldn't load XKB rules");
1036 }
1037
1038 if (gdk_error_trap_pop ())
1039 g_warning ("Error loading XKB rules");
1040
1041 gnome_xkb_info_free_var_defs (xkb_var_defs);
1042 g_free (rules_file_path);
1043}
1044
1045static void
1046set_gtk_im_module (GsdKeyboardManager *manager,
1047 const gchar *new_module)
1048{
1049 GsdKeyboardManagerPrivate *priv = manager->priv;
1050 gchar *current_module;
1051
1052 current_module = g_settings_get_string (priv->interface_settings,
1053 KEY_GTK_IM_MODULE);
1054 if (!g_str_equal (current_module, new_module))
1055 g_settings_set_string (priv->interface_settings,
1056 KEY_GTK_IM_MODULE,
1057 new_module);
1058 g_free (current_module);
1059}
1060
1061static gboolean
1062apply_input_sources_settings (GSettings *settings,
1063 gpointer keys,
1064 gint n_keys,
1065 GsdKeyboardManager *manager)
1066{
1067 GsdKeyboardManagerPrivate *priv = manager->priv;
1068 GVariant *sources;
1069 guint current;
1070 guint n_sources;
1071 const gchar *type = NULL;
1072 const gchar *id = NULL;
1073 gchar *layout = NULL;
1074 gchar *variant = NULL;
1075 gchar **options = NULL;
1076
1077 sources = g_settings_get_value (priv->input_sources_settings, KEY_INPUT_SOURCES);
1078 current = g_settings_get_uint (priv->input_sources_settings, KEY_CURRENT_INPUT_SOURCE);
1079 n_sources = g_variant_n_children (sources);
1080
1081 if (n_sources < 1)
1082 goto exit;
1083
1084 if (current >= n_sources) {
1085 g_settings_set_uint (priv->input_sources_settings,
1086 KEY_CURRENT_INPUT_SOURCE,
1087 n_sources - 1);
1088 goto exit;
1089 }
1090
1091#ifdef HAVE_IBUS
1092 maybe_start_ibus (manager, sources);
1093#endif
1094
1095 g_variant_get_child (sources, current, "(&s&s)", &type, &id);
1096
1097 if (g_str_equal (type, INPUT_SOURCE_TYPE_XKB)) {
1098 const gchar *l, *v;
1099 gnome_xkb_info_get_layout_info (priv->xkb_info, id, NULL, NULL, &l, &v);
1100
1101 layout = g_strdup (l);
1102 variant = g_strdup (v);
1103
1104 if (!layout || !layout[0]) {
1105 g_warning ("Couldn't find XKB input source '%s'", id);
1106 goto exit;
1107 }
1108 set_gtk_im_module (manager, GTK_IM_MODULE_SIMPLE);
1109#ifdef HAVE_IBUS
1110 set_ibus_xkb_engine (manager, id);
1111#endif
1112 } else if (g_str_equal (type, INPUT_SOURCE_TYPE_IBUS)) {
1113#ifdef HAVE_IBUS
1114 IBusEngineDesc *engine_desc = NULL;
1115
1116 if (priv->session_is_fallback)
1117 goto exit;
1118
1119 if (priv->ibus_engines)
1120 engine_desc = g_hash_table_lookup (priv->ibus_engines, id);
1121 else
1122 goto exit; /* we'll be called again when ibus is up and running */
1123
1124 if (engine_desc) {
1125 const gchar *ibus_layout;
1126 ibus_layout = ibus_engine_desc_get_layout (engine_desc);
1127
1128 if (ibus_layout) {
1129 layout = layout_from_ibus_layout (ibus_layout);
1130 variant = variant_from_ibus_layout (ibus_layout);
1131 options = options_from_ibus_layout (ibus_layout);
1132 }
1133 } else {
1134 g_warning ("Couldn't find IBus input source '%s'", id);
1135 goto exit;
1136 }
1137
1138 set_gtk_im_module (manager, GTK_IM_MODULE_IBUS);
1139 set_ibus_engine (manager, id);
1140#else
1141 g_warning ("IBus input source type specified but IBus support was not compiled");
1142#endif
1143 } else {
1144 g_warning ("Unknown input source type '%s'", type);
1145 }
1146
1147 exit:
1148 apply_xkb_settings (manager, layout, variant, options);
1149 g_variant_unref (sources);
1150 g_free (layout);
1151 g_free (variant);
1152 g_strfreev (options);
1153 /* Prevent individual "changed" signal invocations since we
1154 don't need them. */
1155 return TRUE;
1156}
1157
1158static void
1159apply_bell (GsdKeyboardManager *manager)
1160{
1161 GSettings *settings;
1162 XKeyboardControl kbdcontrol;
1163 gboolean click;
1164 int bell_volume;
1165 int bell_pitch;
1166 int bell_duration;
1167 GsdBellMode bell_mode;
1168 int click_volume;
1169
1170 g_debug ("Applying the bell settings");
1171 settings = manager->priv->settings;
1172 click = g_settings_get_boolean (settings, KEY_CLICK);
1173 click_volume = g_settings_get_int (settings, KEY_CLICK_VOLUME);
1174
1175 bell_pitch = g_settings_get_int (settings, KEY_BELL_PITCH);
1176 bell_duration = g_settings_get_int (settings, KEY_BELL_DURATION);
1177
1178 bell_mode = g_settings_get_enum (settings, KEY_BELL_MODE);
1179 bell_volume = (bell_mode == GSD_BELL_MODE_ON) ? 50 : 0;
1180
1181 /* as percentage from 0..100 inclusive */
1182 if (click_volume < 0) {
1183 click_volume = 0;
1184 } else if (click_volume > 100) {
1185 click_volume = 100;
1186 }
1187 kbdcontrol.key_click_percent = click ? click_volume : 0;
1188 kbdcontrol.bell_percent = bell_volume;
1189 kbdcontrol.bell_pitch = bell_pitch;
1190 kbdcontrol.bell_duration = bell_duration;
1191
1192 gdk_error_trap_push ();
1193 XChangeKeyboardControl (GDK_DISPLAY_XDISPLAY (gdk_display_get_default ()),
1194 KBKeyClickPercent | KBBellPercent | KBBellPitch | KBBellDuration,
1195 &kbdcontrol);
1196
1197 XSync (GDK_DISPLAY_XDISPLAY (gdk_display_get_default ()), FALSE);
1198 gdk_error_trap_pop_ignored ();
1199}
1200
1201static void
1202apply_numlock (GsdKeyboardManager *manager)
1203{
1204 GSettings *settings;
1205 gboolean rnumlock;
1206
1207 g_debug ("Applying the num-lock settings");
1208 settings = manager->priv->settings;
1209 rnumlock = g_settings_get_boolean (settings, KEY_REMEMBER_NUMLOCK_STATE);
1210 manager->priv->old_state = g_settings_get_enum (manager->priv->settings, KEY_NUMLOCK_STATE);
1211
1212 gdk_error_trap_push ();
1213 if (rnumlock) {
1214 g_debug ("Remember num-lock is set, so applying setting '%s'",
1215 num_lock_state_to_string (manager->priv->old_state));
1216 numlock_set_xkb_state (manager->priv->old_state);
1217 }
1218
1219 XSync (GDK_DISPLAY_XDISPLAY (gdk_display_get_default ()), FALSE);
1220 gdk_error_trap_pop_ignored ();
1221}
1222
1223static void
1224apply_repeat (GsdKeyboardManager *manager)
1225{
1226 GSettings *settings;
1227 gboolean repeat;
1228 guint interval;
1229 guint delay;
1230
1231 g_debug ("Applying the repeat settings");
1232 settings = manager->priv->settings;
1233 repeat = g_settings_get_boolean (settings, KEY_REPEAT);
1234 interval = g_settings_get_uint (settings, KEY_INTERVAL);
1235 delay = g_settings_get_uint (settings, KEY_DELAY);
1236
1237 gdk_error_trap_push ();
1238 if (repeat) {
1239 gboolean rate_set = FALSE;
1240
1241 XAutoRepeatOn (GDK_DISPLAY_XDISPLAY (gdk_display_get_default ()));
1242 /* Use XKB in preference */
1243 rate_set = xkb_set_keyboard_autorepeat_rate (delay, interval);
1244
1245 if (!rate_set)
1246 g_warning ("Neither XKeyboard not Xfree86's keyboard extensions are available,\n"
1247 "no way to support keyboard autorepeat rate settings");
1248 } else {
1249 XAutoRepeatOff (GDK_DISPLAY_XDISPLAY (gdk_display_get_default ()));
1250 }
1251
1252 XSync (GDK_DISPLAY_XDISPLAY (gdk_display_get_default ()), FALSE);
1253 gdk_error_trap_pop_ignored ();
1254}
1255
1256static void
1257apply_all_settings (GsdKeyboardManager *manager)
1258{
1259 apply_repeat (manager);
1260 apply_bell (manager);
1261 apply_numlock (manager);
1262}
1263
1264static void
1265set_input_sources_switcher (GsdKeyboardManager *manager,
1266 gboolean state)
1267{
1268 if (state) {
1269 GError *error = NULL;
1270 char *args[2];
1271
1272 if (manager->priv->input_sources_switcher_spawned)
1273 set_input_sources_switcher (manager, FALSE);
1274
1275 args[0] = LIBEXECDIR "/gsd-input-sources-switcher";
1276 args[1] = NULL;
1277
1278 g_spawn_async (NULL, args, NULL,
1279 0, NULL, NULL,
1280 &manager->priv->input_sources_switcher_pid, &error);
1281
1282 manager->priv->input_sources_switcher_spawned = (error == NULL);
1283
1284 if (error) {
1285 g_warning ("Couldn't spawn %s: %s", args[0], error->message);
1286 g_error_free (error);
1287 }
1288 } else if (manager->priv->input_sources_switcher_spawned) {
1289 kill (manager->priv->input_sources_switcher_pid, SIGHUP);
1290 g_spawn_close_pid (manager->priv->input_sources_switcher_pid);
1291 manager->priv->input_sources_switcher_spawned = FALSE;
1292 }
1293}
1294
1295static gboolean
1296enable_switcher (GsdKeyboardManager *manager)
1297{
1298 GsdInputSourcesSwitcher switcher;
1299
1300 switcher = g_settings_get_enum (manager->priv->settings, KEY_SWITCHER);
1301
1302 return switcher != GSD_INPUT_SOURCES_SWITCHER_OFF;
1303}
1304
1305static void
1306settings_changed (GSettings *settings,
1307 const char *key,
1308 GsdKeyboardManager *manager)
1309{
1310 if (g_strcmp0 (key, KEY_CLICK) == 0||
1311 g_strcmp0 (key, KEY_CLICK_VOLUME) == 0 ||
1312 g_strcmp0 (key, KEY_BELL_PITCH) == 0 ||
1313 g_strcmp0 (key, KEY_BELL_DURATION) == 0 ||
1314 g_strcmp0 (key, KEY_BELL_MODE) == 0) {
1315 g_debug ("Bell setting '%s' changed, applying bell settings", key);
1316 apply_bell (manager);
1317 } else if (g_strcmp0 (key, KEY_REMEMBER_NUMLOCK_STATE) == 0) {
1318 g_debug ("Remember Num-Lock state '%s' changed, applying num-lock settings", key);
1319 apply_numlock (manager);
1320 } else if (g_strcmp0 (key, KEY_NUMLOCK_STATE) == 0) {
1321 g_debug ("Num-Lock state '%s' changed, will apply at next startup", key);
1322 } else if (g_strcmp0 (key, KEY_REPEAT) == 0 ||
1323 g_strcmp0 (key, KEY_INTERVAL) == 0 ||
1324 g_strcmp0 (key, KEY_DELAY) == 0) {
1325 g_debug ("Key repeat setting '%s' changed, applying key repeat settings", key);
1326 apply_repeat (manager);
1327 } else if (g_strcmp0 (key, KEY_SWITCHER) == 0) {
1328 set_input_sources_switcher (manager, enable_switcher (manager));
1329 } else {
1330 g_warning ("Unhandled settings change, key '%s'", key);
1331 }
1332
1333}
1334
1335static void
1336device_added_cb (GdkDeviceManager *device_manager,
1337 GdkDevice *device,
1338 GsdKeyboardManager *manager)
1339{
1340 GdkInputSource source;
1341
1342 source = gdk_device_get_source (device);
1343 if (source == GDK_SOURCE_KEYBOARD) {
1344 g_debug ("New keyboard plugged in, applying all settings");
1345 apply_all_settings (manager);
1346 apply_input_sources_settings (manager->priv->input_sources_settings, NULL, 0, manager);
1347 run_custom_command (device, COMMAND_DEVICE_ADDED);
1348 }
1349}
1350
1351static void
1352device_removed_cb (GdkDeviceManager *device_manager,
1353 GdkDevice *device,
1354 GsdKeyboardManager *manager)
1355{
1356 GdkInputSource source;
1357
1358 source = gdk_device_get_source (device);
1359 if (source == GDK_SOURCE_KEYBOARD) {
1360 run_custom_command (device, COMMAND_DEVICE_REMOVED);
1361 }
1362}
1363
1364static void
1365set_devicepresence_handler (GsdKeyboardManager *manager)
1366{
1367 GdkDeviceManager *device_manager;
1368
1369 device_manager = gdk_display_get_device_manager (gdk_display_get_default ());
1370
1371 manager->priv->device_added_id = g_signal_connect (G_OBJECT (device_manager), "device-added",
1372 G_CALLBACK (device_added_cb), manager);
1373 manager->priv->device_removed_id = g_signal_connect (G_OBJECT (device_manager), "device-removed",
1374 G_CALLBACK (device_removed_cb), manager);
1375 manager->priv->device_manager = device_manager;
1376}
1377
1378static void
1379create_sources_from_current_xkb_config (GSettings *settings)
1380{
1381 GVariantBuilder builder;
1382 XkbRF_VarDefsRec *xkb_var_defs;
1383 gchar *tmp;
1384 gchar **layouts = NULL;
1385 gchar **variants = NULL;
1386 guint i, n;
1387
1388 gnome_xkb_info_get_var_defs (&tmp, &xkb_var_defs);
1389 g_free (tmp);
1390
1391 if (xkb_var_defs->layout)
1392 layouts = g_strsplit (xkb_var_defs->layout, ",", 0);
1393 if (xkb_var_defs->variant)
1394 variants = g_strsplit (xkb_var_defs->variant, ",", 0);
1395
1396 gnome_xkb_info_free_var_defs (xkb_var_defs);
1397
1398 if (!layouts)
1399 goto out;
1400
1401 if (variants && variants[0])
1402 n = MIN (g_strv_length (layouts), g_strv_length (variants));
1403 else
1404 n = g_strv_length (layouts);
1405
1406 g_variant_builder_init (&builder, G_VARIANT_TYPE ("a(ss)"));
1407 for (i = 0; i < n && layouts[i][0]; ++i) {
1408 if (variants && variants[i] && variants[i][0])
1409 tmp = g_strdup_printf ("%s+%s", layouts[i], variants[i]);
1410 else
1411 tmp = g_strdup (layouts[i]);
1412
1413 g_variant_builder_add (&builder, "(ss)", INPUT_SOURCE_TYPE_XKB, tmp);
1414 g_free (tmp);
1415 }
1416 g_settings_set_value (settings, KEY_INPUT_SOURCES, g_variant_builder_end (&builder));
1417out:
1418 g_strfreev (layouts);
1419 g_strfreev (variants);
1420}
1421
1422static void
1423convert_libgnomekbd_options (GSettings *settings)
1424{
1425 GPtrArray *opt_array;
1426 GSettings *libgnomekbd_settings;
1427 gchar **options, **o;
1428
1429 if (!schema_is_installed ("org.gnome.libgnomekbd.keyboard"))
1430 return;
1431
1432 opt_array = g_ptr_array_new_with_free_func (g_free);
1433
1434 libgnomekbd_settings = g_settings_new ("org.gnome.libgnomekbd.keyboard");
1435 options = g_settings_get_strv (libgnomekbd_settings, "options");
1436
1437 for (o = options; *o; ++o) {
1438 gchar **strv;
1439
1440 strv = g_strsplit (*o, "\t", 2);
1441 if (strv[0] && strv[1]) {
1442 /* We don't want the group switcher because
1443 * it's incompatible with the way we use XKB
1444 * groups. */
1445 if (!g_str_has_prefix (strv[1], "grp:"))
1446 g_ptr_array_add (opt_array, g_strdup (strv[1]));
1447 }
1448 g_strfreev (strv);
1449 }
1450 g_ptr_array_add (opt_array, NULL);
1451
1452 g_settings_set_strv (settings, KEY_KEYBOARD_OPTIONS, (const gchar * const*) opt_array->pdata);
1453
1454 g_strfreev (options);
1455 g_object_unref (libgnomekbd_settings);
1456 g_ptr_array_free (opt_array, TRUE);
1457}
1458
1459static void
1460convert_libgnomekbd_layouts (GSettings *settings)
1461{
1462 GVariantBuilder builder;
1463 GSettings *libgnomekbd_settings;
1464 gchar **layouts, **l;
1465
1466 if (!schema_is_installed ("org.gnome.libgnomekbd.keyboard"))
1467 return;
1468
1469 init_builder_with_sources (&builder, settings);
1470
1471 libgnomekbd_settings = g_settings_new ("org.gnome.libgnomekbd.keyboard");
1472 layouts = g_settings_get_strv (libgnomekbd_settings, "layouts");
1473
1474 for (l = layouts; *l; ++l) {
1475 gchar *id;
1476 gchar **strv;
1477
1478 strv = g_strsplit (*l, "\t", 2);
1479 if (strv[0] && !strv[1])
1480 id = g_strdup (strv[0]);
1481 else if (strv[0] && strv[1])
1482 id = g_strdup_printf ("%s+%s", strv[0], strv[1]);
1483 else
1484 id = NULL;
1485
1486 if (id)
1487 g_variant_builder_add (&builder, "(ss)", INPUT_SOURCE_TYPE_XKB, id);
1488
1489 g_free (id);
1490 g_strfreev (strv);
1491 }
1492
1493 g_settings_set_value (settings, KEY_INPUT_SOURCES, g_variant_builder_end (&builder));
1494
1495 g_strfreev (layouts);
1496 g_object_unref (libgnomekbd_settings);
1497}
1498
1499static void
1500maybe_convert_old_settings (GSettings *settings)
1501{
1502 GVariant *sources;
1503 gchar **options;
1504 gchar *stamp_dir_path = NULL;
1505 gchar *stamp_file_path = NULL;
1506 GError *error = NULL;
1507
1508 stamp_dir_path = g_build_filename (g_get_user_data_dir (), PACKAGE_NAME, NULL);
1509 if (g_mkdir_with_parents (stamp_dir_path, 0755)) {
1510 g_warning ("Failed to create directory %s: %s", stamp_dir_path, g_strerror (errno));
1511 goto out;
1512 }
1513
1514 stamp_file_path = g_build_filename (stamp_dir_path, "input-sources-converted", NULL);
1515 if (g_file_test (stamp_file_path, G_FILE_TEST_EXISTS))
1516 goto out;
1517
1518 sources = g_settings_get_value (settings, KEY_INPUT_SOURCES);
1519 if (g_variant_n_children (sources) < 1) {
1520 convert_libgnomekbd_layouts (settings);
1521#ifdef HAVE_IBUS
1522 convert_ibus (settings);
1523#endif
1524 }
1525 g_variant_unref (sources);
1526
1527 options = g_settings_get_strv (settings, KEY_KEYBOARD_OPTIONS);
1528 if (g_strv_length (options) < 1)
1529 convert_libgnomekbd_options (settings);
1530 g_strfreev (options);
1531
1532 if (!g_file_set_contents (stamp_file_path, "", 0, &error)) {
1533 g_warning ("%s", error->message);
1534 g_error_free (error);
1535 }
1536out:
1537 g_free (stamp_file_path);
1538 g_free (stamp_dir_path);
1539}
1540
1541static void
1542maybe_create_input_sources (GsdKeyboardManager *manager)
1543{
1544 GSettings *settings;
1545 GVariant *sources;
1546
1547 settings = manager->priv->input_sources_settings;
1548
1549 if (g_getenv ("RUNNING_UNDER_GDM")) {
1550 create_sources_from_current_xkb_config (settings);
1551 return;
1552 }
1553
1554 maybe_convert_old_settings (settings);
1555
1556 /* if we still don't have anything do some educated guesses */
1557 sources = g_settings_get_value (settings, KEY_INPUT_SOURCES);
1558 if (g_variant_n_children (sources) < 1) {
1559 create_sources_from_current_xkb_config (settings);
1560#ifdef HAVE_IBUS
1561 add_ibus_sources_from_locale (settings);
1562#endif
1563 }
1564 g_variant_unref (sources);
1565}
1566
1567static gboolean
1568start_keyboard_idle_cb (GsdKeyboardManager *manager)
1569{
1570 gnome_settings_profile_start (NULL);
1571
1572 g_debug ("Starting keyboard manager");
1573
1574 manager->priv->settings = g_settings_new (GSD_KEYBOARD_DIR);
1575
1576 xkb_init (manager);
1577
1578 set_devicepresence_handler (manager);
1579
1580 manager->priv->input_sources_settings = g_settings_new (GNOME_DESKTOP_INPUT_SOURCES_DIR);
1581 manager->priv->interface_settings = g_settings_new (GNOME_DESKTOP_INTERFACE_DIR);
1582 manager->priv->xkb_info = gnome_xkb_info_new ();
1583
1584 maybe_create_input_sources (manager);
1585
1586#ifdef HAVE_IBUS
1587 /* We don't want to touch IBus until we are sure this isn't a
1588 fallback session. */
1589 manager->priv->session_is_fallback = TRUE;
1590 manager->priv->ibus_cancellable = g_cancellable_new ();
1591 g_bus_get (G_BUS_TYPE_SESSION,
1592 manager->priv->ibus_cancellable,
1593 (GAsyncReadyCallback)got_bus,
1594 manager);
1595#else
1596 apply_input_sources_settings (manager->priv->input_sources_settings, NULL, 0, manager);
1597#endif
1598 /* apply current settings before we install the callback */
1599 g_debug ("Started the keyboard plugin, applying all settings");
1600 apply_all_settings (manager);
1601
1602 g_signal_connect (G_OBJECT (manager->priv->settings), "changed",
1603 G_CALLBACK (settings_changed), manager);
1604 g_signal_connect (G_OBJECT (manager->priv->input_sources_settings), "change-event",
1605 G_CALLBACK (apply_input_sources_settings), manager);
1606
1607 install_xkb_filter (manager);
1608 set_input_sources_switcher (manager, enable_switcher (manager));
1609
1610 gnome_settings_profile_end (NULL);
1611
1612 manager->priv->start_idle_id = 0;
1613
1614 return FALSE;
1615}
1616
1617gboolean
1618gsd_keyboard_manager_start (GsdKeyboardManager *manager,
1619 GError **error)
1620{
1621 gnome_settings_profile_start (NULL);
1622
1623 if (check_xkb_extension (manager) == FALSE) {
1624 g_debug ("XKB is not supported, not applying any settings");
1625 return TRUE;
1626 }
1627
1628 manager->priv->start_idle_id = g_idle_add ((GSourceFunc) start_keyboard_idle_cb, manager);
1629
1630 gnome_settings_profile_end (NULL);
1631
1632 return TRUE;
1633}
1634
1635void
1636gsd_keyboard_manager_stop (GsdKeyboardManager *manager)
1637{
1638 GsdKeyboardManagerPrivate *p = manager->priv;
1639
1640 g_debug ("Stopping keyboard manager");
1641
1642 g_clear_object (&p->settings);
1643 g_clear_object (&p->input_sources_settings);
1644 g_clear_object (&p->interface_settings);
1645 g_clear_object (&p->xkb_info);
1646
1647#ifdef HAVE_IBUS
1648 clear_ibus (manager);
1649#endif
1650
1651 if (p->device_manager != NULL) {
1652 g_signal_handler_disconnect (p->device_manager, p->device_added_id);
1653 g_signal_handler_disconnect (p->device_manager, p->device_removed_id);
1654 p->device_manager = NULL;
1655 }
1656
1657 remove_xkb_filter (manager);
1658
1659 set_input_sources_switcher (manager, FALSE);
1660}
1661
1662static void
1663gsd_keyboard_manager_class_init (GsdKeyboardManagerClass *klass)
1664{
1665 GObjectClass *object_class = G_OBJECT_CLASS (klass);
1666
1667 object_class->finalize = gsd_keyboard_manager_finalize;
1668
1669 g_type_class_add_private (klass, sizeof (GsdKeyboardManagerPrivate));
1670}
1671
1672static void
1673gsd_keyboard_manager_init (GsdKeyboardManager *manager)
1674{
1675 manager->priv = GSD_KEYBOARD_MANAGER_GET_PRIVATE (manager);
1676}
1677
1678static void
1679gsd_keyboard_manager_finalize (GObject *object)
1680{
1681 GsdKeyboardManager *keyboard_manager;
1682
1683 g_return_if_fail (object != NULL);
1684 g_return_if_fail (GSD_IS_KEYBOARD_MANAGER (object));
1685
1686 keyboard_manager = GSD_KEYBOARD_MANAGER (object);
1687
1688 g_return_if_fail (keyboard_manager->priv != NULL);
1689
1690 if (keyboard_manager->priv->start_idle_id != 0)
1691 g_source_remove (keyboard_manager->priv->start_idle_id);
1692
1693 G_OBJECT_CLASS (gsd_keyboard_manager_parent_class)->finalize (object);
1694}
1695
1696GsdKeyboardManager *
1697gsd_keyboard_manager_new (void)
1698{
1699 if (manager_object != NULL) {
1700 g_object_ref (manager_object);
1701 } else {
1702 manager_object = g_object_new (GSD_TYPE_KEYBOARD_MANAGER, NULL);
1703 g_object_add_weak_pointer (manager_object,
1704 (gpointer *) &manager_object);
1705 }
1706
1707 return GSD_KEYBOARD_MANAGER (manager_object);
1708}
17090
=== added directory '.pc/tune-syndaemon.patch'
=== added file '.pc/tune-syndaemon.patch/.timestamp'
=== added directory '.pc/tune-syndaemon.patch/plugins'
=== added directory '.pc/tune-syndaemon.patch/plugins/mouse'
=== added file '.pc/tune-syndaemon.patch/plugins/mouse/gsd-mouse-manager.c'
--- .pc/tune-syndaemon.patch/plugins/mouse/gsd-mouse-manager.c 1970-01-01 00:00:00 +0000
+++ .pc/tune-syndaemon.patch/plugins/mouse/gsd-mouse-manager.c 2013-08-29 18:58:42 +0000
@@ -0,0 +1,1354 @@
1/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*-
2 *
3 * Copyright (C) 2007 William Jon McCann <mccann@jhu.edu>
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
18 *
19 */
20
21#include "config.h"
22
23#include <sys/types.h>
24#include <sys/wait.h>
25#include <stdlib.h>
26#include <stdio.h>
27#include <unistd.h>
28#include <string.h>
29#include <errno.h>
30#include <math.h>
31#ifdef __linux
32#include <sys/prctl.h>
33#endif
34
35#include <locale.h>
36
37#include <glib.h>
38#include <glib/gi18n.h>
39#include <gio/gio.h>
40#include <gtk/gtk.h>
41#include <gdk/gdk.h>
42#include <gdk/gdkx.h>
43#include <gdk/gdkkeysyms.h>
44#include <X11/keysym.h>
45#include <X11/Xatom.h>
46
47#include <X11/extensions/XInput.h>
48#include <X11/extensions/XIproto.h>
49
50#include "gnome-settings-profile.h"
51#include "gsd-mouse-manager.h"
52#include "gsd-input-helper.h"
53#include "gsd-enums.h"
54
55#define GSD_MOUSE_MANAGER_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), GSD_TYPE_MOUSE_MANAGER, GsdMouseManagerPrivate))
56
57#define SETTINGS_MOUSE_DIR "org.gnome.settings-daemon.peripherals.mouse"
58#define SETTINGS_TOUCHPAD_DIR "org.gnome.settings-daemon.peripherals.touchpad"
59
60/* Keys for both touchpad and mouse */
61#define KEY_LEFT_HANDED "left-handed" /* a boolean for mouse, an enum for touchpad */
62#define KEY_MOTION_ACCELERATION "motion-acceleration"
63#define KEY_MOTION_THRESHOLD "motion-threshold"
64
65/* Touchpad settings */
66#define KEY_TOUCHPAD_DISABLE_W_TYPING "disable-while-typing"
67#define KEY_PAD_HORIZ_SCROLL "horiz-scroll-enabled"
68#define KEY_SCROLL_METHOD "scroll-method"
69#define KEY_TAP_TO_CLICK "tap-to-click"
70#define KEY_TOUCHPAD_ENABLED "touchpad-enabled"
71#define KEY_NATURAL_SCROLL_ENABLED "natural-scroll"
72
73/* Mouse settings */
74#define KEY_LOCATE_POINTER "locate-pointer"
75#define KEY_DWELL_CLICK_ENABLED "dwell-click-enabled"
76#define KEY_SECONDARY_CLICK_ENABLED "secondary-click-enabled"
77#define KEY_MIDDLE_BUTTON_EMULATION "middle-button-enabled"
78
79struct GsdMouseManagerPrivate
80{
81 guint start_idle_id;
82 GSettings *touchpad_settings;
83 GSettings *mouse_settings;
84 GSettings *mouse_a11y_settings;
85 GdkDeviceManager *device_manager;
86 guint device_added_id;
87 guint device_removed_id;
88 GHashTable *blacklist;
89
90 gboolean mousetweaks_daemon_running;
91 gboolean syndaemon_spawned;
92 GPid syndaemon_pid;
93 gboolean locate_pointer_spawned;
94 GPid locate_pointer_pid;
95};
96
97static void gsd_mouse_manager_class_init (GsdMouseManagerClass *klass);
98static void gsd_mouse_manager_init (GsdMouseManager *mouse_manager);
99static void gsd_mouse_manager_finalize (GObject *object);
100static void set_tap_to_click (GdkDevice *device,
101 gboolean state,
102 gboolean left_handed);
103static void set_natural_scroll (GsdMouseManager *manager,
104 GdkDevice *device,
105 gboolean natural_scroll);
106
107G_DEFINE_TYPE (GsdMouseManager, gsd_mouse_manager, G_TYPE_OBJECT)
108
109static gpointer manager_object = NULL;
110
111
112static GObject *
113gsd_mouse_manager_constructor (GType type,
114 guint n_construct_properties,
115 GObjectConstructParam *construct_properties)
116{
117 GsdMouseManager *mouse_manager;
118
119 mouse_manager = GSD_MOUSE_MANAGER (G_OBJECT_CLASS (gsd_mouse_manager_parent_class)->constructor (type,
120 n_construct_properties,
121 construct_properties));
122
123 return G_OBJECT (mouse_manager);
124}
125
126static void
127gsd_mouse_manager_dispose (GObject *object)
128{
129 G_OBJECT_CLASS (gsd_mouse_manager_parent_class)->dispose (object);
130}
131
132static void
133gsd_mouse_manager_class_init (GsdMouseManagerClass *klass)
134{
135 GObjectClass *object_class = G_OBJECT_CLASS (klass);
136
137 object_class->constructor = gsd_mouse_manager_constructor;
138 object_class->dispose = gsd_mouse_manager_dispose;
139 object_class->finalize = gsd_mouse_manager_finalize;
140
141 g_type_class_add_private (klass, sizeof (GsdMouseManagerPrivate));
142}
143
144static XDevice *
145open_gdk_device (GdkDevice *device)
146{
147 XDevice *xdevice;
148 int id;
149
150 g_object_get (G_OBJECT (device), "device-id", &id, NULL);
151
152 gdk_error_trap_push ();
153
154 xdevice = XOpenDevice (GDK_DISPLAY_XDISPLAY (gdk_display_get_default ()), id);
155
156 if (gdk_error_trap_pop () != 0)
157 return NULL;
158
159 return xdevice;
160}
161
162static gboolean
163device_is_blacklisted (GsdMouseManager *manager,
164 GdkDevice *device)
165{
166 int id;
167 g_object_get (G_OBJECT (device), "device-id", &id, NULL);
168 if (g_hash_table_lookup (manager->priv->blacklist, GINT_TO_POINTER (id)) != NULL) {
169 g_debug ("device %s (%d) is blacklisted", gdk_device_get_name (device), id);
170 return TRUE;
171 }
172 return FALSE;
173}
174
175static gboolean
176device_is_ignored (GsdMouseManager *manager,
177 GdkDevice *device)
178{
179 GdkInputSource source;
180 const char *name;
181
182 if (device_is_blacklisted (manager, device))
183 return TRUE;
184
185 source = gdk_device_get_source (device);
186 if (source != GDK_SOURCE_MOUSE &&
187 source != GDK_SOURCE_TOUCHPAD &&
188 source != GDK_SOURCE_CURSOR)
189 return TRUE;
190
191 name = gdk_device_get_name (device);
192 if (name != NULL && g_str_equal ("Virtual core XTEST pointer", name))
193 return TRUE;
194
195 return FALSE;
196}
197
198static void
199configure_button_layout (guchar *buttons,
200 gint n_buttons,
201 gboolean left_handed)
202{
203 const gint left_button = 1;
204 gint right_button;
205 gint i;
206
207 /* if the button is higher than 2 (3rd button) then it's
208 * probably one direction of a scroll wheel or something else
209 * uninteresting
210 */
211 right_button = MIN (n_buttons, 3);
212
213 /* If we change things we need to make sure we only swap buttons.
214 * If we end up with multiple physical buttons assigned to the same
215 * logical button the server will complain. This code assumes physical
216 * button 0 is the physical left mouse button, and that the physical
217 * button other than 0 currently assigned left_button or right_button
218 * is the physical right mouse button.
219 */
220
221 /* check if the current mapping satisfies the above assumptions */
222 if (buttons[left_button - 1] != left_button &&
223 buttons[left_button - 1] != right_button)
224 /* The current mapping is weird. Swapping buttons is probably not a
225 * good idea.
226 */
227 return;
228
229 /* check if we are left_handed and currently not swapped */
230 if (left_handed && buttons[left_button - 1] == left_button) {
231 /* find the right button */
232 for (i = 0; i < n_buttons; i++) {
233 if (buttons[i] == right_button) {
234 buttons[i] = left_button;
235 break;
236 }
237 }
238 /* swap the buttons */
239 buttons[left_button - 1] = right_button;
240 }
241 /* check if we are not left_handed but are swapped */
242 else if (!left_handed && buttons[left_button - 1] == right_button) {
243 /* find the right button */
244 for (i = 0; i < n_buttons; i++) {
245 if (buttons[i] == left_button) {
246 buttons[i] = right_button;
247 break;
248 }
249 }
250 /* swap the buttons */
251 buttons[left_button - 1] = left_button;
252 }
253}
254
255static gboolean
256xinput_device_has_buttons (GdkDevice *device)
257{
258 int i;
259 XAnyClassInfo *class_info;
260
261 /* FIXME can we use the XDevice's classes here instead? */
262 XDeviceInfo *device_info, *info;
263 gint n_devices;
264 int id;
265
266 /* Find the XDeviceInfo for the GdkDevice */
267 g_object_get (G_OBJECT (device), "device-id", &id, NULL);
268
269 device_info = XListInputDevices (GDK_DISPLAY_XDISPLAY (gdk_display_get_default ()), &n_devices);
270 if (device_info == NULL)
271 return FALSE;
272
273 info = NULL;
274 for (i = 0; i < n_devices; i++) {
275 if (device_info[i].id == id) {
276 info = &device_info[i];
277 break;
278 }
279 }
280 if (info == NULL)
281 goto bail;
282
283 class_info = info->inputclassinfo;
284 for (i = 0; i < info->num_classes; i++) {
285 if (class_info->class == ButtonClass) {
286 XButtonInfo *button_info;
287
288 button_info = (XButtonInfo *) class_info;
289 if (button_info->num_buttons > 0) {
290 XFreeDeviceList (device_info);
291 return TRUE;
292 }
293 }
294
295 class_info = (XAnyClassInfo *) (((guchar *) class_info) +
296 class_info->length);
297 }
298
299bail:
300 XFreeDeviceList (device_info);
301
302 return FALSE;
303}
304
305static gboolean
306touchpad_has_single_button (XDevice *device)
307{
308 Atom type, prop;
309 int format;
310 unsigned long nitems, bytes_after;
311 unsigned char *data;
312 gboolean is_single_button = FALSE;
313 int rc;
314
315 prop = XInternAtom (GDK_DISPLAY_XDISPLAY (gdk_display_get_default ()), "Synaptics Capabilities", False);
316 if (!prop)
317 return FALSE;
318
319 gdk_error_trap_push ();
320 rc = XGetDeviceProperty (GDK_DISPLAY_XDISPLAY (gdk_display_get_default ()), device, prop, 0, 1, False,
321 XA_INTEGER, &type, &format, &nitems,
322 &bytes_after, &data);
323 if (rc == Success && type == XA_INTEGER && format == 8 && nitems >= 3)
324 is_single_button = (data[0] == 1 && data[1] == 0 && data[2] == 0);
325
326 if (rc == Success)
327 XFree (data);
328
329 gdk_error_trap_pop_ignored ();
330
331 return is_single_button;
332}
333
334static void
335set_left_handed (GsdMouseManager *manager,
336 GdkDevice *device,
337 gboolean mouse_left_handed,
338 gboolean touchpad_left_handed)
339{
340 XDevice *xdevice;
341 guchar *buttons;
342 gsize buttons_capacity = 16;
343 gboolean left_handed;
344 gint n_buttons;
345
346 if (!xinput_device_has_buttons (device))
347 return;
348
349 xdevice = open_gdk_device (device);
350 if (xdevice == NULL)
351 return;
352
353 g_debug ("setting handedness on %s", gdk_device_get_name (device));
354
355 buttons = g_new (guchar, buttons_capacity);
356
357 /* If the device is a touchpad, swap tap buttons
358 * around too, otherwise a tap would be a right-click */
359 if (device_is_touchpad (xdevice)) {
360 gboolean tap = g_settings_get_boolean (manager->priv->touchpad_settings, KEY_TAP_TO_CLICK);
361 gboolean single_button = touchpad_has_single_button (xdevice);
362
363 left_handed = touchpad_left_handed;
364
365 if (tap && !single_button)
366 set_tap_to_click (device, tap, left_handed);
367
368 if (single_button)
369 goto out;
370 } else {
371 left_handed = mouse_left_handed;
372 }
373
374 n_buttons = XGetDeviceButtonMapping (GDK_DISPLAY_XDISPLAY (gdk_display_get_default ()), xdevice,
375 buttons,
376 buttons_capacity);
377
378 while (n_buttons > buttons_capacity) {
379 buttons_capacity = n_buttons;
380 buttons = (guchar *) g_realloc (buttons,
381 buttons_capacity * sizeof (guchar));
382
383 n_buttons = XGetDeviceButtonMapping (GDK_DISPLAY_XDISPLAY (gdk_display_get_default ()), xdevice,
384 buttons,
385 buttons_capacity);
386 }
387
388 configure_button_layout (buttons, n_buttons, left_handed);
389
390 gdk_error_trap_push ();
391 XSetDeviceButtonMapping (GDK_DISPLAY_XDISPLAY (gdk_display_get_default ()), xdevice, buttons, n_buttons);
392 gdk_error_trap_pop_ignored ();
393
394out:
395 XCloseDevice (GDK_DISPLAY_XDISPLAY (gdk_display_get_default ()), xdevice);
396 g_free (buttons);
397}
398
399static void
400set_motion (GsdMouseManager *manager,
401 GdkDevice *device)
402{
403 XDevice *xdevice;
404 XPtrFeedbackControl feedback;
405 XFeedbackState *states, *state;
406 int num_feedbacks;
407 int numerator, denominator;
408 gfloat motion_acceleration;
409 int motion_threshold;
410 GSettings *settings;
411 guint i;
412
413 xdevice = open_gdk_device (device);
414 if (xdevice == NULL)
415 return;
416
417 g_debug ("setting motion on %s", gdk_device_get_name (device));
418
419 if (device_is_touchpad (xdevice))
420 settings = manager->priv->touchpad_settings;
421 else
422 settings = manager->priv->mouse_settings;
423
424 /* Calculate acceleration */
425 motion_acceleration = g_settings_get_double (settings, KEY_MOTION_ACCELERATION);
426
427 if (motion_acceleration >= 1.0) {
428 /* we want to get the acceleration, with a resolution of 0.5
429 */
430 if ((motion_acceleration - floor (motion_acceleration)) < 0.25) {
431 numerator = floor (motion_acceleration);
432 denominator = 1;
433 } else if ((motion_acceleration - floor (motion_acceleration)) < 0.5) {
434 numerator = ceil (2.0 * motion_acceleration);
435 denominator = 2;
436 } else if ((motion_acceleration - floor (motion_acceleration)) < 0.75) {
437 numerator = floor (2.0 *motion_acceleration);
438 denominator = 2;
439 } else {
440 numerator = ceil (motion_acceleration);
441 denominator = 1;
442 }
443 } else if (motion_acceleration < 1.0 && motion_acceleration > 0) {
444 /* This we do to 1/10ths */
445 numerator = floor (motion_acceleration * 10) + 1;
446 denominator= 10;
447 } else {
448 numerator = -1;
449 denominator = -1;
450 }
451
452 /* And threshold */
453 motion_threshold = g_settings_get_int (settings, KEY_MOTION_THRESHOLD);
454
455 /* Get the list of feedbacks for the device */
456 states = XGetFeedbackControl (GDK_DISPLAY_XDISPLAY (gdk_display_get_default ()), xdevice, &num_feedbacks);
457 if (states == NULL)
458 goto out;
459 state = (XFeedbackState *) states;
460 for (i = 0; i < num_feedbacks; i++) {
461 if (state->class == PtrFeedbackClass) {
462 /* And tell the device */
463 feedback.class = PtrFeedbackClass;
464 feedback.length = sizeof (XPtrFeedbackControl);
465 feedback.id = state->id;
466 feedback.threshold = motion_threshold;
467 feedback.accelNum = numerator;
468 feedback.accelDenom = denominator;
469
470 g_debug ("Setting accel %d/%d, threshold %d for device '%s'",
471 numerator, denominator, motion_threshold, gdk_device_get_name (device));
472
473 XChangeFeedbackControl (GDK_DISPLAY_XDISPLAY (gdk_display_get_default ()),
474 xdevice,
475 DvAccelNum | DvAccelDenom | DvThreshold,
476 (XFeedbackControl *) &feedback);
477
478 break;
479 }
480 state = (XFeedbackState *) ((char *) state + state->length);
481 }
482
483 XFreeFeedbackList (states);
484
485 out:
486
487 XCloseDevice (GDK_DISPLAY_XDISPLAY (gdk_display_get_default ()), xdevice);
488}
489
490static void
491set_middle_button (GsdMouseManager *manager,
492 GdkDevice *device,
493 gboolean middle_button)
494{
495 Atom prop;
496 XDevice *xdevice;
497 Atom type;
498 int format;
499 unsigned long nitems, bytes_after;
500 unsigned char *data;
501 int rc;
502
503 prop = XInternAtom (GDK_DISPLAY_XDISPLAY (gdk_display_get_default ()),
504 "Evdev Middle Button Emulation", True);
505
506 if (!prop) /* no evdev devices */
507 return;
508
509 xdevice = open_gdk_device (device);
510 if (xdevice == NULL)
511 return;
512
513 g_debug ("setting middle button on %s", gdk_device_get_name (device));
514
515 gdk_error_trap_push ();
516
517 rc = XGetDeviceProperty (GDK_DISPLAY_XDISPLAY (gdk_display_get_default ()),
518 xdevice, prop, 0, 1, False, XA_INTEGER, &type, &format,
519 &nitems, &bytes_after, &data);
520
521 if (rc == Success && format == 8 && type == XA_INTEGER && nitems == 1) {
522 data[0] = middle_button ? 1 : 0;
523
524 XChangeDeviceProperty (GDK_DISPLAY_XDISPLAY (gdk_display_get_default ()),
525 xdevice, prop, type, format, PropModeReplace, data, nitems);
526 }
527
528 if (gdk_error_trap_pop ())
529 g_warning ("Error in setting middle button emulation on \"%s\"", gdk_device_get_name (device));
530
531 if (rc == Success)
532 XFree (data);
533
534 XCloseDevice (GDK_DISPLAY_XDISPLAY (gdk_display_get_default ()), xdevice);
535}
536
537/* Ensure that syndaemon dies together with us, to avoid running several of
538 * them */
539static void
540setup_syndaemon (gpointer user_data)
541{
542#ifdef __linux
543 prctl (PR_SET_PDEATHSIG, SIGHUP);
544#endif
545}
546
547static gboolean
548have_program_in_path (const char *name)
549{
550 gchar *path;
551 gboolean result;
552
553 path = g_find_program_in_path (name);
554 result = (path != NULL);
555 g_free (path);
556 return result;
557}
558
559static void
560syndaemon_died (GPid pid, gint status, gpointer user_data)
561{
562 GsdMouseManager *manager = GSD_MOUSE_MANAGER (user_data);
563
564 g_debug ("syndaemon stopped with status %i", status);
565 g_spawn_close_pid (pid);
566 manager->priv->syndaemon_spawned = FALSE;
567}
568
569static int
570set_disable_w_typing (GsdMouseManager *manager, gboolean state)
571{
572 if (state && touchpad_is_present ()) {
573 GError *error = NULL;
574 GPtrArray *args;
575
576 if (manager->priv->syndaemon_spawned)
577 return 0;
578
579 if (!have_program_in_path ("syndaemon"))
580 return 0;
581
582 args = g_ptr_array_new ();
583
584 g_ptr_array_add (args, "syndaemon");
585 g_ptr_array_add (args, "-i");
586 g_ptr_array_add (args, "1.0");
587 g_ptr_array_add (args, "-t");
588 g_ptr_array_add (args, "-K");
589 g_ptr_array_add (args, "-R");
590 g_ptr_array_add (args, NULL);
591
592 /* we must use G_SPAWN_DO_NOT_REAP_CHILD to avoid
593 * double-forking, otherwise syndaemon will immediately get
594 * killed again through (PR_SET_PDEATHSIG when the intermediate
595 * process dies */
596 g_spawn_async (g_get_home_dir (), (char **) args->pdata, NULL,
597 G_SPAWN_SEARCH_PATH|G_SPAWN_DO_NOT_REAP_CHILD, setup_syndaemon, NULL,
598 &manager->priv->syndaemon_pid, &error);
599
600 manager->priv->syndaemon_spawned = (error == NULL);
601 g_ptr_array_free (args, FALSE);
602
603 if (error) {
604 g_warning ("Failed to launch syndaemon: %s", error->message);
605 g_settings_set_boolean (manager->priv->touchpad_settings, KEY_TOUCHPAD_DISABLE_W_TYPING, FALSE);
606 g_error_free (error);
607 } else {
608 g_child_watch_add (manager->priv->syndaemon_pid, syndaemon_died, manager);
609 g_debug ("Launched syndaemon");
610 }
611 } else if (manager->priv->syndaemon_spawned) {
612 kill (manager->priv->syndaemon_pid, SIGHUP);
613 g_spawn_close_pid (manager->priv->syndaemon_pid);
614 manager->priv->syndaemon_spawned = FALSE;
615 g_debug ("Killed syndaemon");
616 }
617
618 return 0;
619}
620
621static void
622set_tap_to_click (GdkDevice *device,
623 gboolean state,
624 gboolean left_handed)
625{
626 int format, rc;
627 unsigned long nitems, bytes_after;
628 XDevice *xdevice;
629 unsigned char* data;
630 Atom prop, type;
631
632 prop = XInternAtom (GDK_DISPLAY_XDISPLAY (gdk_display_get_default ()), "Synaptics Tap Action", False);
633 if (!prop)
634 return;
635
636 xdevice = open_gdk_device (device);
637 if (xdevice == NULL)
638 return;
639
640 if (!device_is_touchpad (xdevice)) {
641 XCloseDevice (GDK_DISPLAY_XDISPLAY (gdk_display_get_default ()), xdevice);
642 return;
643 }
644
645 g_debug ("setting tap to click on %s", gdk_device_get_name (device));
646
647 gdk_error_trap_push ();
648 rc = XGetDeviceProperty (GDK_DISPLAY_XDISPLAY (gdk_display_get_default ()), xdevice, prop, 0, 2,
649 False, XA_INTEGER, &type, &format, &nitems,
650 &bytes_after, &data);
651
652 if (rc == Success && type == XA_INTEGER && format == 8 && nitems >= 7) {
653 /* Set MR mapping for corner tapping on the right side*/
654 data[0] = (state) ? 2 : 0;
655 data[1] = (state) ? 3 : 0;
656
657 /* Set RLM mapping for 1/2/3 fingers*/
658 data[4] = (state) ? ((left_handed) ? 3 : 1) : 0;
659 data[5] = (state) ? ((left_handed) ? 1 : 3) : 0;
660 data[6] = 0; /* Disable three touch tap so gestures work */
661 XChangeDeviceProperty (GDK_DISPLAY_XDISPLAY (gdk_display_get_default ()), xdevice, prop, XA_INTEGER, 8,
662 PropModeReplace, data, nitems);
663 }
664
665 if (rc == Success)
666 XFree (data);
667
668 if (gdk_error_trap_pop ())
669 g_warning ("Error in setting tap to click on \"%s\"", gdk_device_get_name (device));
670
671 XCloseDevice (GDK_DISPLAY_XDISPLAY (gdk_display_get_default ()), xdevice);
672}
673
674static void
675set_horiz_scroll (GdkDevice *device,
676 gboolean state)
677{
678 int rc;
679 XDevice *xdevice;
680 Atom act_type, prop_edge, prop_twofinger;
681 int act_format;
682 unsigned long nitems, bytes_after;
683 unsigned char *data;
684
685 prop_edge = XInternAtom (GDK_DISPLAY_XDISPLAY (gdk_display_get_default ()), "Synaptics Edge Scrolling", False);
686 prop_twofinger = XInternAtom (GDK_DISPLAY_XDISPLAY (gdk_display_get_default ()), "Synaptics Two-Finger Scrolling", False);
687
688 if (!prop_edge || !prop_twofinger)
689 return;
690
691 xdevice = open_gdk_device (device);
692 if (xdevice == NULL)
693 return;
694
695 if (!device_is_touchpad (xdevice)) {
696 XCloseDevice (GDK_DISPLAY_XDISPLAY (gdk_display_get_default ()), xdevice);
697 return;
698 }
699
700 g_debug ("setting horiz scroll on %s", gdk_device_get_name (device));
701
702 gdk_error_trap_push ();
703 rc = XGetDeviceProperty (GDK_DISPLAY_XDISPLAY (gdk_display_get_default ()), xdevice,
704 prop_edge, 0, 1, False,
705 XA_INTEGER, &act_type, &act_format, &nitems,
706 &bytes_after, &data);
707 if (rc == Success && act_type == XA_INTEGER &&
708 act_format == 8 && nitems >= 2) {
709 data[1] = (state && data[0]);
710 XChangeDeviceProperty (GDK_DISPLAY_XDISPLAY (gdk_display_get_default ()), xdevice,
711 prop_edge, XA_INTEGER, 8,
712 PropModeReplace, data, nitems);
713 }
714
715 XFree (data);
716
717 rc = XGetDeviceProperty (GDK_DISPLAY_XDISPLAY (gdk_display_get_default ()), xdevice,
718 prop_twofinger, 0, 1, False,
719 XA_INTEGER, &act_type, &act_format, &nitems,
720 &bytes_after, &data);
721 if (rc == Success && act_type == XA_INTEGER &&
722 act_format == 8 && nitems >= 2) {
723 data[1] = (state && data[0]);
724 XChangeDeviceProperty (GDK_DISPLAY_XDISPLAY (gdk_display_get_default ()), xdevice,
725 prop_twofinger, XA_INTEGER, 8,
726 PropModeReplace, data, nitems);
727 }
728
729 if (gdk_error_trap_pop ())
730 g_warning ("Error in setting horiz scroll on \"%s\"", gdk_device_get_name (device));
731
732 if (rc == Success)
733 XFree (data);
734
735 XCloseDevice (GDK_DISPLAY_XDISPLAY (gdk_display_get_default ()), xdevice);
736
737}
738
739static void
740set_edge_scroll (GdkDevice *device,
741 GsdTouchpadScrollMethod method)
742{
743 int rc;
744 XDevice *xdevice;
745 Atom act_type, prop_edge, prop_twofinger;
746 int act_format;
747 unsigned long nitems, bytes_after;
748 unsigned char *data;
749
750 prop_edge = XInternAtom (GDK_DISPLAY_XDISPLAY (gdk_display_get_default ()), "Synaptics Edge Scrolling", False);
751 prop_twofinger = XInternAtom (GDK_DISPLAY_XDISPLAY (gdk_display_get_default ()), "Synaptics Two-Finger Scrolling", False);
752
753 if (!prop_edge || !prop_twofinger)
754 return;
755
756 xdevice = open_gdk_device (device);
757 if (xdevice == NULL)
758 return;
759
760 if (!device_is_touchpad (xdevice)) {
761 XCloseDevice (GDK_DISPLAY_XDISPLAY (gdk_display_get_default ()), xdevice);
762 return;
763 }
764
765 g_debug ("setting edge scroll on %s", gdk_device_get_name (device));
766
767 gdk_error_trap_push ();
768 rc = XGetDeviceProperty (GDK_DISPLAY_XDISPLAY (gdk_display_get_default ()), xdevice,
769 prop_edge, 0, 1, False,
770 XA_INTEGER, &act_type, &act_format, &nitems,
771 &bytes_after, &data);
772 if (rc == Success && act_type == XA_INTEGER &&
773 act_format == 8 && nitems >= 2) {
774 data[0] = (method == GSD_TOUCHPAD_SCROLL_METHOD_EDGE_SCROLLING) ? 1 : 0;
775 XChangeDeviceProperty (GDK_DISPLAY_XDISPLAY (gdk_display_get_default ()), xdevice,
776 prop_edge, XA_INTEGER, 8,
777 PropModeReplace, data, nitems);
778 }
779
780 XFree (data);
781
782 rc = XGetDeviceProperty (GDK_DISPLAY_XDISPLAY (gdk_display_get_default ()), xdevice,
783 prop_twofinger, 0, 1, False,
784 XA_INTEGER, &act_type, &act_format, &nitems,
785 &bytes_after, &data);
786 if (rc == Success && act_type == XA_INTEGER &&
787 act_format == 8 && nitems >= 2) {
788 data[0] = (method == GSD_TOUCHPAD_SCROLL_METHOD_TWO_FINGER_SCROLLING) ? 1 : 0;
789 XChangeDeviceProperty (GDK_DISPLAY_XDISPLAY (gdk_display_get_default ()), xdevice,
790 prop_twofinger, XA_INTEGER, 8,
791 PropModeReplace, data, nitems);
792 }
793
794 if (gdk_error_trap_pop ())
795 g_warning ("Error in setting edge scroll on \"%s\"", gdk_device_get_name (device));
796
797 if (rc == Success)
798 XFree (data);
799
800 XCloseDevice (GDK_DISPLAY_XDISPLAY (gdk_display_get_default ()), xdevice);
801}
802
803static void
804set_touchpad_disabled (GdkDevice *device)
805{
806 int id;
807 XDevice *xdevice;
808
809 g_object_get (G_OBJECT (device), "device-id", &id, NULL);
810
811 g_debug ("Trying to set device disabled for \"%s\" (%d)", gdk_device_get_name (device), id);
812
813 xdevice = open_gdk_device (device);
814 if (xdevice == NULL)
815 return;
816
817 if (!device_is_touchpad (xdevice)) {
818 XCloseDevice (GDK_DISPLAY_XDISPLAY (gdk_display_get_default ()), xdevice);
819 return;
820 }
821
822 if (set_device_enabled (id, FALSE) == FALSE)
823 g_warning ("Error disabling device \"%s\" (%d)", gdk_device_get_name (device), id);
824 else
825 g_debug ("Disabled device \"%s\" (%d)", gdk_device_get_name (device), id);
826
827 XCloseDevice (GDK_DISPLAY_XDISPLAY (gdk_display_get_default ()), xdevice);
828}
829
830static void
831set_touchpad_enabled (int id)
832{
833 XDevice *xdevice;
834
835 g_debug ("Trying to set device enabled for %d", id);
836
837 gdk_error_trap_push ();
838 xdevice = XOpenDevice (GDK_DISPLAY_XDISPLAY (gdk_display_get_default ()), id);
839 if (gdk_error_trap_pop () != 0)
840 return;
841
842 if (!device_is_touchpad (xdevice)) {
843 XCloseDevice (GDK_DISPLAY_XDISPLAY (gdk_display_get_default ()), xdevice);
844 return;
845 }
846
847 if (set_device_enabled (id, TRUE) == FALSE)
848 g_warning ("Error enabling device \"%d\"", id);
849 else
850 g_debug ("Enabled device %d", id);
851
852 XCloseDevice (GDK_DISPLAY_XDISPLAY (gdk_display_get_default ()), xdevice);
853}
854
855static void
856set_locate_pointer (GsdMouseManager *manager,
857 gboolean state)
858{
859 if (state) {
860 GError *error = NULL;
861 char *args[2];
862
863 if (manager->priv->locate_pointer_spawned)
864 return;
865
866 args[0] = LIBEXECDIR "/gsd-locate-pointer";
867 args[1] = NULL;
868
869 g_spawn_async (NULL, args, NULL,
870 0, NULL, NULL,
871 &manager->priv->locate_pointer_pid, &error);
872
873 manager->priv->locate_pointer_spawned = (error == NULL);
874
875 if (error) {
876 g_settings_set_boolean (manager->priv->mouse_settings, KEY_LOCATE_POINTER, FALSE);
877 g_error_free (error);
878 }
879
880 } else if (manager->priv->locate_pointer_spawned) {
881 kill (manager->priv->locate_pointer_pid, SIGHUP);
882 g_spawn_close_pid (manager->priv->locate_pointer_pid);
883 manager->priv->locate_pointer_spawned = FALSE;
884 }
885}
886
887static void
888set_mousetweaks_daemon (GsdMouseManager *manager,
889 gboolean dwell_click_enabled,
890 gboolean secondary_click_enabled)
891{
892 GError *error = NULL;
893 gchar *comm;
894 gboolean run_daemon = dwell_click_enabled || secondary_click_enabled;
895
896 if (run_daemon || manager->priv->mousetweaks_daemon_running)
897 comm = g_strdup_printf ("mousetweaks %s",
898 run_daemon ? "" : "-s");
899 else
900 return;
901
902 if (run_daemon)
903 manager->priv->mousetweaks_daemon_running = TRUE;
904
905 if (! g_spawn_command_line_async (comm, &error)) {
906 if (error->code == G_SPAWN_ERROR_NOENT && run_daemon) {
907 GtkWidget *dialog;
908
909 if (dwell_click_enabled) {
910 g_settings_set_boolean (manager->priv->mouse_a11y_settings,
911 KEY_DWELL_CLICK_ENABLED, FALSE);
912 } else if (secondary_click_enabled) {
913 g_settings_set_boolean (manager->priv->mouse_a11y_settings,
914 KEY_SECONDARY_CLICK_ENABLED, FALSE);
915 }
916
917 dialog = gtk_message_dialog_new (NULL, 0,
918 GTK_MESSAGE_WARNING,
919 GTK_BUTTONS_OK,
920 _("Could not enable mouse accessibility features"));
921 gtk_message_dialog_format_secondary_text (GTK_MESSAGE_DIALOG (dialog),
922 _("Mouse accessibility requires Mousetweaks "
923 "to be installed on your system."));
924 gtk_window_set_title (GTK_WINDOW (dialog), _("Universal Access"));
925 gtk_window_set_icon_name (GTK_WINDOW (dialog),
926 "preferences-desktop-accessibility");
927 gtk_dialog_run (GTK_DIALOG (dialog));
928 gtk_widget_destroy (dialog);
929 }
930 g_error_free (error);
931 }
932 g_free (comm);
933}
934
935static gboolean
936get_touchpad_handedness (GsdMouseManager *manager, gboolean mouse_left_handed)
937{
938 switch (g_settings_get_enum (manager->priv->touchpad_settings, KEY_LEFT_HANDED)) {
939 case GSD_TOUCHPAD_HANDEDNESS_RIGHT:
940 return FALSE;
941 case GSD_TOUCHPAD_HANDEDNESS_LEFT:
942 return TRUE;
943 case GSD_TOUCHPAD_HANDEDNESS_MOUSE:
944 return mouse_left_handed;
945 default:
946 g_assert_not_reached ();
947 }
948}
949
950static void
951set_mouse_settings (GsdMouseManager *manager,
952 GdkDevice *device)
953{
954 gboolean mouse_left_handed, touchpad_left_handed;
955
956 mouse_left_handed = g_settings_get_boolean (manager->priv->mouse_settings, KEY_LEFT_HANDED);
957 touchpad_left_handed = get_touchpad_handedness (manager, mouse_left_handed);
958 set_left_handed (manager, device, mouse_left_handed, touchpad_left_handed);
959
960 set_motion (manager, device);
961 set_middle_button (manager, device, g_settings_get_boolean (manager->priv->mouse_settings, KEY_MIDDLE_BUTTON_EMULATION));
962
963 set_tap_to_click (device, g_settings_get_boolean (manager->priv->touchpad_settings, KEY_TAP_TO_CLICK), touchpad_left_handed);
964 set_edge_scroll (device, g_settings_get_enum (manager->priv->touchpad_settings, KEY_SCROLL_METHOD));
965 set_horiz_scroll (device, g_settings_get_boolean (manager->priv->touchpad_settings, KEY_PAD_HORIZ_SCROLL));
966 set_natural_scroll (manager, device, g_settings_get_boolean (manager->priv->touchpad_settings, KEY_NATURAL_SCROLL_ENABLED));
967 if (g_settings_get_boolean (manager->priv->touchpad_settings, KEY_TOUCHPAD_ENABLED) == FALSE)
968 set_touchpad_disabled (device);
969}
970
971static void
972set_natural_scroll (GsdMouseManager *manager,
973 GdkDevice *device,
974 gboolean natural_scroll)
975{
976 XDevice *xdevice;
977 Atom scrolling_distance, act_type;
978 int rc, act_format;
979 unsigned long nitems, bytes_after;
980 unsigned char *data;
981 glong *ptr;
982
983 xdevice = open_gdk_device (device);
984 if (xdevice == NULL)
985 return;
986
987 if (!device_is_touchpad (xdevice)) {
988 XCloseDevice (GDK_DISPLAY_XDISPLAY (gdk_display_get_default ()), xdevice);
989 return;
990 }
991
992 g_debug ("Trying to set %s for \"%s\"",
993 natural_scroll ? "natural (reverse) scroll" : "normal scroll",
994 gdk_device_get_name (device));
995
996 scrolling_distance = XInternAtom (GDK_DISPLAY_XDISPLAY (gdk_display_get_default ()),
997 "Synaptics Scrolling Distance", False);
998
999 gdk_error_trap_push ();
1000 rc = XGetDeviceProperty (GDK_DISPLAY_XDISPLAY (gdk_display_get_default ()), xdevice,
1001 scrolling_distance, 0, 2, False,
1002 XA_INTEGER, &act_type, &act_format, &nitems,
1003 &bytes_after, &data);
1004
1005 if (rc == Success && act_type == XA_INTEGER && act_format == 32 && nitems >= 2) {
1006 ptr = (glong *) data;
1007
1008 if (natural_scroll) {
1009 ptr[0] = -abs(ptr[0]);
1010 ptr[1] = -abs(ptr[1]);
1011 } else {
1012 ptr[0] = abs(ptr[0]);
1013 ptr[1] = abs(ptr[1]);
1014 }
1015
1016 XChangeDeviceProperty (GDK_DISPLAY_XDISPLAY (gdk_display_get_default ()), xdevice,
1017 scrolling_distance, XA_INTEGER, act_format,
1018 PropModeReplace, data, nitems);
1019 }
1020
1021 if (gdk_error_trap_pop ())
1022 g_warning ("Error setting %s for \"%s\"",
1023 natural_scroll ? "natural (reverse) scroll" : "normal scroll",
1024 gdk_device_get_name (device));
1025
1026 if (rc == Success)
1027 XFree (data);
1028
1029 XCloseDevice (GDK_DISPLAY_XDISPLAY (gdk_display_get_default ()), xdevice);
1030}
1031
1032static void
1033mouse_callback (GSettings *settings,
1034 const gchar *key,
1035 GsdMouseManager *manager)
1036{
1037 GList *devices, *l;
1038
1039 if (g_str_equal (key, KEY_DWELL_CLICK_ENABLED) ||
1040 g_str_equal (key, KEY_SECONDARY_CLICK_ENABLED)) {
1041 set_mousetweaks_daemon (manager,
1042 g_settings_get_boolean (settings, KEY_DWELL_CLICK_ENABLED),
1043 g_settings_get_boolean (settings, KEY_SECONDARY_CLICK_ENABLED));
1044 return;
1045 } else if (g_str_equal (key, KEY_LOCATE_POINTER)) {
1046 set_locate_pointer (manager, g_settings_get_boolean (settings, KEY_LOCATE_POINTER));
1047 return;
1048 }
1049
1050 devices = gdk_device_manager_list_devices (manager->priv->device_manager, GDK_DEVICE_TYPE_SLAVE);
1051
1052 for (l = devices; l != NULL; l = l->next) {
1053 GdkDevice *device = l->data;
1054
1055 if (device_is_ignored (manager, device))
1056 continue;
1057
1058 if (g_str_equal (key, KEY_LEFT_HANDED)) {
1059 gboolean mouse_left_handed;
1060 mouse_left_handed = g_settings_get_boolean (settings, KEY_LEFT_HANDED);
1061 set_left_handed (manager, device, mouse_left_handed, get_touchpad_handedness (manager, mouse_left_handed));
1062 } else if (g_str_equal (key, KEY_MOTION_ACCELERATION) ||
1063 g_str_equal (key, KEY_MOTION_THRESHOLD)) {
1064 set_motion (manager, device);
1065 } else if (g_str_equal (key, KEY_MIDDLE_BUTTON_EMULATION)) {
1066 set_middle_button (manager, device, g_settings_get_boolean (settings, KEY_MIDDLE_BUTTON_EMULATION));
1067 }
1068 }
1069 g_list_free (devices);
1070}
1071
1072static void
1073touchpad_callback (GSettings *settings,
1074 const gchar *key,
1075 GsdMouseManager *manager)
1076{
1077 GList *devices, *l;
1078
1079 if (g_str_equal (key, KEY_TOUCHPAD_DISABLE_W_TYPING)) {
1080 set_disable_w_typing (manager, g_settings_get_boolean (manager->priv->touchpad_settings, key));
1081 return;
1082 }
1083
1084 devices = gdk_device_manager_list_devices (manager->priv->device_manager, GDK_DEVICE_TYPE_SLAVE);
1085
1086 for (l = devices; l != NULL; l = l->next) {
1087 GdkDevice *device = l->data;
1088
1089 if (device_is_ignored (manager, device))
1090 continue;
1091
1092 if (g_str_equal (key, KEY_TAP_TO_CLICK)) {
1093 set_tap_to_click (device, g_settings_get_boolean (settings, key),
1094 g_settings_get_boolean (manager->priv->touchpad_settings, KEY_LEFT_HANDED));
1095 } else if (g_str_equal (key, KEY_SCROLL_METHOD)) {
1096 set_edge_scroll (device, g_settings_get_enum (settings, key));
1097 set_horiz_scroll (device, g_settings_get_boolean (settings, KEY_PAD_HORIZ_SCROLL));
1098 } else if (g_str_equal (key, KEY_PAD_HORIZ_SCROLL)) {
1099 set_horiz_scroll (device, g_settings_get_boolean (settings, key));
1100 } else if (g_str_equal (key, KEY_TOUCHPAD_ENABLED)) {
1101 if (g_settings_get_boolean (settings, key) == FALSE)
1102 set_touchpad_disabled (device);
1103 else
1104 set_touchpad_enabled (gdk_x11_device_get_id (device));
1105 } else if (g_str_equal (key, KEY_MOTION_ACCELERATION) ||
1106 g_str_equal (key, KEY_MOTION_THRESHOLD)) {
1107 set_motion (manager, device);
1108 } else if (g_str_equal (key, KEY_LEFT_HANDED)) {
1109 gboolean mouse_left_handed;
1110 mouse_left_handed = g_settings_get_boolean (manager->priv->mouse_settings, KEY_LEFT_HANDED);
1111 set_left_handed (manager, device, mouse_left_handed, get_touchpad_handedness (manager, mouse_left_handed));
1112 } else if (g_str_equal (key, KEY_NATURAL_SCROLL_ENABLED)) {
1113 set_natural_scroll (manager, device, g_settings_get_boolean (settings, key));
1114 }
1115 }
1116 g_list_free (devices);
1117
1118 if (g_str_equal (key, KEY_TOUCHPAD_ENABLED) &&
1119 g_settings_get_boolean (settings, key)) {
1120 devices = get_disabled_devices (manager->priv->device_manager);
1121 for (l = devices; l != NULL; l = l->next) {
1122 int device_id;
1123
1124 device_id = GPOINTER_TO_INT (l->data);
1125 set_touchpad_enabled (device_id);
1126 }
1127 g_list_free (devices);
1128 }
1129}
1130
1131static void
1132device_added_cb (GdkDeviceManager *device_manager,
1133 GdkDevice *device,
1134 GsdMouseManager *manager)
1135{
1136 if (device_is_ignored (manager, device) == FALSE) {
1137 if (run_custom_command (device, COMMAND_DEVICE_ADDED) == FALSE) {
1138 set_mouse_settings (manager, device);
1139 } else {
1140 int id;
1141 g_object_get (G_OBJECT (device), "device-id", &id, NULL);
1142 g_hash_table_insert (manager->priv->blacklist,
1143 GINT_TO_POINTER (id), GINT_TO_POINTER (1));
1144 }
1145
1146 /* If a touchpad was to appear... */
1147 set_disable_w_typing (manager, g_settings_get_boolean (manager->priv->touchpad_settings, KEY_TOUCHPAD_DISABLE_W_TYPING));
1148 }
1149}
1150
1151static void
1152device_removed_cb (GdkDeviceManager *device_manager,
1153 GdkDevice *device,
1154 GsdMouseManager *manager)
1155{
1156 int id;
1157
1158 /* Remove the device from the hash table so that
1159 * device_is_ignored () doesn't check for blacklisted devices */
1160 g_object_get (G_OBJECT (device), "device-id", &id, NULL);
1161 g_hash_table_remove (manager->priv->blacklist,
1162 GINT_TO_POINTER (id));
1163
1164 if (device_is_ignored (manager, device) == FALSE) {
1165 run_custom_command (device, COMMAND_DEVICE_REMOVED);
1166
1167 /* If a touchpad was to disappear... */
1168 set_disable_w_typing (manager, g_settings_get_boolean (manager->priv->touchpad_settings, KEY_TOUCHPAD_DISABLE_W_TYPING));
1169 }
1170}
1171
1172static void
1173set_devicepresence_handler (GsdMouseManager *manager)
1174{
1175 GdkDeviceManager *device_manager;
1176
1177 device_manager = gdk_display_get_device_manager (gdk_display_get_default ());
1178
1179 manager->priv->device_added_id = g_signal_connect (G_OBJECT (device_manager), "device-added",
1180 G_CALLBACK (device_added_cb), manager);
1181 manager->priv->device_removed_id = g_signal_connect (G_OBJECT (device_manager), "device-removed",
1182 G_CALLBACK (device_removed_cb), manager);
1183 manager->priv->device_manager = device_manager;
1184}
1185
1186static void
1187gsd_mouse_manager_init (GsdMouseManager *manager)
1188{
1189 manager->priv = GSD_MOUSE_MANAGER_GET_PRIVATE (manager);
1190 manager->priv->blacklist = g_hash_table_new (g_direct_hash, g_direct_equal);
1191}
1192
1193static gboolean
1194gsd_mouse_manager_idle_cb (GsdMouseManager *manager)
1195{
1196 GList *devices, *l;
1197
1198 gnome_settings_profile_start (NULL);
1199
1200 set_devicepresence_handler (manager);
1201
1202 manager->priv->mouse_settings = g_settings_new (SETTINGS_MOUSE_DIR);
1203 g_signal_connect (manager->priv->mouse_settings, "changed",
1204 G_CALLBACK (mouse_callback), manager);
1205
1206 manager->priv->mouse_a11y_settings = g_settings_new ("org.gnome.desktop.a11y.mouse");
1207 g_signal_connect (manager->priv->mouse_a11y_settings, "changed",
1208 G_CALLBACK (mouse_callback), manager);
1209
1210 manager->priv->touchpad_settings = g_settings_new (SETTINGS_TOUCHPAD_DIR);
1211 g_signal_connect (manager->priv->touchpad_settings, "changed",
1212 G_CALLBACK (touchpad_callback), manager);
1213
1214 manager->priv->syndaemon_spawned = FALSE;
1215
1216 set_locate_pointer (manager, g_settings_get_boolean (manager->priv->mouse_settings, KEY_LOCATE_POINTER));
1217 set_mousetweaks_daemon (manager,
1218 g_settings_get_boolean (manager->priv->mouse_a11y_settings, KEY_DWELL_CLICK_ENABLED),
1219 g_settings_get_boolean (manager->priv->mouse_a11y_settings, KEY_SECONDARY_CLICK_ENABLED));
1220 set_disable_w_typing (manager, g_settings_get_boolean (manager->priv->touchpad_settings, KEY_TOUCHPAD_DISABLE_W_TYPING));
1221
1222 devices = gdk_device_manager_list_devices (manager->priv->device_manager, GDK_DEVICE_TYPE_SLAVE);
1223 for (l = devices; l != NULL; l = l->next) {
1224 GdkDevice *device = l->data;
1225
1226 if (device_is_ignored (manager, device))
1227 continue;
1228
1229 if (run_custom_command (device, COMMAND_DEVICE_PRESENT) == FALSE) {
1230 set_mouse_settings (manager, device);
1231 } else {
1232 int id;
1233 g_object_get (G_OBJECT (device), "device-id", &id, NULL);
1234 g_hash_table_insert (manager->priv->blacklist,
1235 GINT_TO_POINTER (id), GINT_TO_POINTER (1));
1236 }
1237 }
1238 g_list_free (devices);
1239
1240 if (g_settings_get_boolean (manager->priv->touchpad_settings, KEY_TOUCHPAD_ENABLED)) {
1241 devices = get_disabled_devices (manager->priv->device_manager);
1242 for (l = devices; l != NULL; l = l->next) {
1243 int device_id;
1244
1245 device_id = GPOINTER_TO_INT (l->data);
1246 set_touchpad_enabled (device_id);
1247 }
1248 g_list_free (devices);
1249 }
1250
1251 gnome_settings_profile_end (NULL);
1252
1253 manager->priv->start_idle_id = 0;
1254
1255 return FALSE;
1256}
1257
1258gboolean
1259gsd_mouse_manager_start (GsdMouseManager *manager,
1260 GError **error)
1261{
1262 gnome_settings_profile_start (NULL);
1263
1264 if (!supports_xinput_devices ()) {
1265 g_debug ("XInput is not supported, not applying any settings");
1266 return TRUE;
1267 }
1268
1269 manager->priv->start_idle_id = g_idle_add ((GSourceFunc) gsd_mouse_manager_idle_cb, manager);
1270
1271 gnome_settings_profile_end (NULL);
1272
1273 return TRUE;
1274}
1275
1276void
1277gsd_mouse_manager_stop (GsdMouseManager *manager)
1278{
1279 GsdMouseManagerPrivate *p = manager->priv;
1280
1281 g_debug ("Stopping mouse manager");
1282
1283 if (p->device_manager != NULL) {
1284 g_signal_handler_disconnect (p->device_manager, p->device_added_id);
1285 g_signal_handler_disconnect (p->device_manager, p->device_removed_id);
1286 p->device_manager = NULL;
1287 }
1288
1289 if (p->mouse_a11y_settings != NULL) {
1290 g_object_unref (p->mouse_a11y_settings);
1291 p->mouse_a11y_settings = NULL;
1292 }
1293
1294 if (p->mouse_settings != NULL) {
1295 g_object_unref (p->mouse_settings);
1296 p->mouse_settings = NULL;
1297 }
1298
1299 if (p->touchpad_settings != NULL) {
1300 g_object_unref (p->touchpad_settings);
1301 p->touchpad_settings = NULL;
1302 }
1303
1304 set_locate_pointer (manager, FALSE);
1305}
1306
1307static void
1308gsd_mouse_manager_finalize (GObject *object)
1309{
1310 GsdMouseManager *mouse_manager;
1311
1312 g_return_if_fail (object != NULL);
1313 g_return_if_fail (GSD_IS_MOUSE_MANAGER (object));
1314
1315 mouse_manager = GSD_MOUSE_MANAGER (object);
1316
1317 g_return_if_fail (mouse_manager->priv != NULL);
1318
1319 if (mouse_manager->priv->blacklist != NULL)
1320 g_hash_table_destroy (mouse_manager->priv->blacklist);
1321
1322 if (mouse_manager->priv->start_idle_id != 0)
1323 g_source_remove (mouse_manager->priv->start_idle_id);
1324
1325 if (mouse_manager->priv->device_manager != NULL) {
1326 g_signal_handler_disconnect (mouse_manager->priv->device_manager, mouse_manager->priv->device_added_id);
1327 g_signal_handler_disconnect (mouse_manager->priv->device_manager, mouse_manager->priv->device_removed_id);
1328 }
1329
1330 if (mouse_manager->priv->mouse_settings != NULL)
1331 g_object_unref (mouse_manager->priv->mouse_settings);
1332
1333 if (mouse_manager->priv->mouse_a11y_settings != NULL)
1334 g_object_unref (mouse_manager->priv->mouse_a11y_settings);
1335
1336 if (mouse_manager->priv->touchpad_settings != NULL)
1337 g_object_unref (mouse_manager->priv->touchpad_settings);
1338
1339 G_OBJECT_CLASS (gsd_mouse_manager_parent_class)->finalize (object);
1340}
1341
1342GsdMouseManager *
1343gsd_mouse_manager_new (void)
1344{
1345 if (manager_object != NULL) {
1346 g_object_ref (manager_object);
1347 } else {
1348 manager_object = g_object_new (GSD_TYPE_MOUSE_MANAGER, NULL);
1349 g_object_add_weak_pointer (manager_object,
1350 (gpointer *) &manager_object);
1351 }
1352
1353 return GSD_MOUSE_MANAGER (manager_object);
1354}
01355
=== modified file 'debian/changelog'
--- debian/changelog 2013-08-29 11:14:56 +0000
+++ debian/changelog 2013-08-29 18:58:42 +0000
@@ -1,3 +1,10 @@
1gnome-settings-daemon (3.6.4-0ubuntu20) saucy; urgency=low
2
3 * "Disable while typing" should disable cursor movements (LP: #1215463),
4 debian/patches/tune-syndaemon.patch: Launch syndaemon with '-i 0.5 -K -R'
5
6 -- Jason Gerard DeRose <jason@system76.com> Thu, 29 Aug 2013 12:56:37 -0600
7
1gnome-settings-daemon (3.6.4-0ubuntu19) saucy; urgency=low8gnome-settings-daemon (3.6.4-0ubuntu19) saucy; urgency=low
29
3 * Install the ibus dbus service (LP: #1194138)10 * Install the ibus dbus service (LP: #1194138)
411
=== modified file 'debian/patches/series'
--- debian/patches/series 2013-08-29 16:10:41 +0000
+++ debian/patches/series 2013-08-29 18:58:42 +0000
@@ -31,3 +31,4 @@
31git_keyboard_Adapt_to_gnome_xkb_info_API_change.patch31git_keyboard_Adapt_to_gnome_xkb_info_API_change.patch
32git_keyboard_Adapt_to_gnome_xkb_info_API_change_2.patch32git_keyboard_Adapt_to_gnome_xkb_info_API_change_2.patch
33git_keybindings_add_screen_reader_toggle.patch33git_keybindings_add_screen_reader_toggle.patch
34tune-syndaemon.patch
3435
=== added file 'debian/patches/tune-syndaemon.patch'
--- debian/patches/tune-syndaemon.patch 1970-01-01 00:00:00 +0000
+++ debian/patches/tune-syndaemon.patch 2013-08-29 18:58:42 +0000
@@ -0,0 +1,20 @@
1Description: Tweaks syndaemon arguments so it disables cursor movement when typing
2Author: Jason Gerard DeRose <jason@system76.com>
3Bug-Ubuntu: https://bugs.launchpad.net/bugs/1215463
4Forwarded: no
5Last-Update: 2013-08-26
6
7---
8
9--- a/plugins/mouse/gsd-mouse-manager.c
10+++ b/plugins/mouse/gsd-mouse-manager.c
11@@ -583,8 +583,7 @@
12
13 g_ptr_array_add (args, "syndaemon");
14 g_ptr_array_add (args, "-i");
15- g_ptr_array_add (args, "1.0");
16- g_ptr_array_add (args, "-t");
17+ g_ptr_array_add (args, "0.5");
18 g_ptr_array_add (args, "-K");
19 g_ptr_array_add (args, "-R");
20 g_ptr_array_add (args, NULL);
021
=== modified file 'plugins/mouse/gsd-mouse-manager.c'
--- plugins/mouse/gsd-mouse-manager.c 2012-11-21 17:16:23 +0000
+++ plugins/mouse/gsd-mouse-manager.c 2013-08-29 18:58:42 +0000
@@ -583,8 +583,7 @@
583583
584 g_ptr_array_add (args, "syndaemon");584 g_ptr_array_add (args, "syndaemon");
585 g_ptr_array_add (args, "-i");585 g_ptr_array_add (args, "-i");
586 g_ptr_array_add (args, "1.0");586 g_ptr_array_add (args, "0.5");
587 g_ptr_array_add (args, "-t");
588 g_ptr_array_add (args, "-K");587 g_ptr_array_add (args, "-K");
589 g_ptr_array_add (args, "-R");588 g_ptr_array_add (args, "-R");
590 g_ptr_array_add (args, NULL);589 g_ptr_array_add (args, NULL);

Subscribers

People subscribed via source and target branches