Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(8)

Side by Side Diff: chromeos_keyboard.cc

Issue 6735026: Remove chromeos_keyboard* (Closed) Base URL: http://git.chromium.org/git/cros.git@master
Patch Set: re-upload Created 9 years, 8 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « chromeos_keyboard.h ('k') | chromeos_keyboard_unittest.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
(Empty)
1 // Copyright (c) 2011 The Chromium OS Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4 //
5 // DEPRECATED. TODO(satorux): Remove this file.
6
7 #include "chromeos_keyboard.h"
8
9 #include <utility>
10
11 #include <X11/XKBlib.h>
12 #include <X11/Xlib.h>
13 #include <glib.h>
14 #include <stdlib.h>
15 #include <string.h>
16
17 #include "base/logging.h"
18 #include "base/singleton.h"
19 #include "base/string_util.h"
20 #include "chromeos/process.h"
21
22 namespace {
23
24 // The default keyboard layout name in the xorg config file.
25 const char kDefaultLayoutName[] = "us";
26 // The command we use to set the current XKB layout and modifier key mapping.
27 // TODO(yusukes): Use libxkbfile.so instead of the command (crosbug.com/13105)
28 const char kSetxkbmapCommand[] = "/usr/bin/setxkbmap";
29 // See the comment at ModifierKey in the .h file.
30 chromeos::ModifierKey kCustomizableKeys[] = {
31 chromeos::kSearchKey,
32 chromeos::kLeftControlKey,
33 chromeos::kLeftAltKey
34 };
35
36 // This is a wrapper class around Display, that opens and closes X display in
37 // the constructor and destructor.
38 class ScopedDisplay {
39 public:
40 explicit ScopedDisplay(Display* display) : display_(display) {
41 if (!display_) {
42 LOG(ERROR) << "NULL display_ is passed";
43 }
44 }
45
46 ~ScopedDisplay() {
47 if (display_) {
48 XCloseDisplay(display_);
49 }
50 }
51
52 Display* get() const {
53 return display_;
54 }
55
56 private:
57 Display* display_;
58
59 DISALLOW_COPY_AND_ASSIGN(ScopedDisplay);
60 };
61
62 // A singleton class which wraps the setxkbmap command.
63 class XKeyboard {
64 public:
65 // Returns the singleton instance of the class. Use LeakySingletonTraits.
66 // We don't delete the instance at exit.
67 static XKeyboard* Get() {
68 return Singleton<XKeyboard, LeakySingletonTraits<XKeyboard> >::get();
69 }
70
71 // Sets the current keyboard layout to |layout_name|. This function does not
72 // change the current mapping of the modifier keys. Returns true on success.
73 bool SetLayout(const std::string& layout_name) {
74 if (SetLayoutInternal(layout_name, current_modifier_map_)) {
75 current_layout_name_ = layout_name;
76 return true;
77 }
78 return false;
79 }
80
81 // Remaps modifier keys. This function does not change the current keyboard
82 // layout. Returns true on success.
83 bool RemapModifierKeys(const chromeos::ModifierMap& modifier_map) {
84 if (SetLayoutInternal(current_layout_name_, modifier_map)) {
85 current_modifier_map_ = modifier_map;
86 return true;
87 }
88 return false;
89 }
90
91 // Gets the current auto-repeat mode of the keyboard. The result is stored in
92 // |mode|. Returns true on success.
93 // TODO(yusukes): Remove this function.
94 bool GetAutoRepeatEnabled(bool* enabled) {
95 DCHECK(enabled);
96 ScopedDisplay display(XOpenDisplay(NULL));
97 if (!display.get()) {
98 return false;
99 }
100 XKeyboardState values = {};
101 XGetKeyboardControl(display.get(), &values);
102 if (values.global_auto_repeat == 0) {
103 *enabled = false;
104 } else {
105 *enabled = true;
106 }
107 return true;
108 }
109
110 // Turns on and off the auto-repeat of the keyboard. Returns true on success.
111 // TODO(yusukes): Remove this function.
112 bool SetAutoRepeatEnabled(bool enabled) {
113 ScopedDisplay display(XOpenDisplay(NULL));
114 if (!display.get()) {
115 return false;
116 }
117 if (enabled) {
118 XAutoRepeatOn(display.get());
119 } else {
120 XAutoRepeatOff(display.get());
121 }
122 DLOG(INFO) << "Set auto-repeat mode to: " << (enabled ? "on" : "off");
123 return true;
124 }
125
126 // Gets the current auto-repeat rate of the keyboard. The result is stored in
127 // |out_rate|. Returns true on success.
128 // TODO(yusukes): Remove this function.
129 bool GetAutoRepeatRate(chromeos::AutoRepeatRate* out_rate) {
130 ScopedDisplay display(XOpenDisplay(NULL));
131 if (!display.get()) {
132 return false;
133 }
134 if (XkbGetAutoRepeatRate(display.get(), XkbUseCoreKbd,
135 &(out_rate->initial_delay_in_ms),
136 &(out_rate->repeat_interval_in_ms)) != True) {
137 out_rate->initial_delay_in_ms = 0;
138 out_rate->repeat_interval_in_ms = 0;
139 return false;
140 }
141 return true;
142 }
143
144 // Sets the auto-repeat rate of the keyboard, initial delay in ms, and repeat
145 // interval in ms. Returns true on success.
146 // TODO(yusukes): Call this function in non-UI thread or in an idle callback.
147 bool SetAutoRepeatRate(const chromeos::AutoRepeatRate& rate) {
148 // TODO(yusukes): write auto tests for the function.
149 ScopedDisplay display(XOpenDisplay(NULL));
150 if (!display.get()) {
151 return false;
152 }
153
154 DLOG(INFO) << "Set auto-repeat rate to: "
155 << rate.initial_delay_in_ms << " ms delay, "
156 << rate.repeat_interval_in_ms << " ms interval";
157 if (XkbSetAutoRepeatRate(display.get(), XkbUseCoreKbd,
158 rate.initial_delay_in_ms,
159 rate.repeat_interval_in_ms) != True) {
160 LOG(ERROR) << "Failed to set auto-repeat rate";
161 return false;
162 }
163 return true;
164 }
165
166 private:
167 friend struct DefaultSingletonTraits<XKeyboard>;
168
169 XKeyboard() : current_layout_name_(kDefaultLayoutName) {
170 for (size_t i = 0; i < arraysize(kCustomizableKeys); ++i) {
171 chromeos::ModifierKey key = kCustomizableKeys[i];
172 current_modifier_map_.push_back(chromeos::ModifierKeyPair(key, key));
173 }
174 }
175 ~XKeyboard() {
176 }
177
178 // This function is used by SetLayout() and RemapModifierKeys(). Calls
179 // setxkbmap command if needed, and updates the last_full_layout_name_ cache.
180 bool SetLayoutInternal(const std::string& layout_name,
181 const chromeos::ModifierMap& modifier_map) {
182 const std::string layouts_to_set = chromeos::CreateFullXkbLayoutName(
183 layout_name, modifier_map);
184 if (layouts_to_set.empty()) {
185 return false;
186 }
187
188 const std::string current_layout = chromeos::CreateFullXkbLayoutName(
189 current_layout_name_, current_modifier_map_);
190 if (current_layout == layouts_to_set) {
191 DLOG(INFO) << "The requested layout is already set: " << layouts_to_set;
192 return true;
193 }
194
195 // Turn off caps lock if there is no kCapsLockKey in the remapped keys.
196 if (!ContainsModifierKeyAsReplacement(
197 modifier_map, chromeos::kCapsLockKey)) {
198 chromeos::SetCapsLockEnabled(false);
199 }
200
201 ExecuteSetLayoutCommand(layouts_to_set);
202 return true;
203 }
204
205 // Executes 'setxkbmap -layout ...' command asynchronously.
206 // TODO(yusukes): Use libxkbfile.so instead of the command (crosbug.com/13105)
207 void ExecuteSetLayoutCommand(const std::string& layouts_to_set) {
208 chromeos::ProcessImpl process;
209 process.AddArg(kSetxkbmapCommand);
210 process.AddStringOption("-layout", layouts_to_set);
211 if (!process.Start()) {
212 LOG(ERROR) << "Failed to execute setxkbmap: " << layouts_to_set;
213 return;
214 }
215 // g_child_watch_add is necessary to prevent the process from becoming a
216 // zombie.
217 g_child_watch_add(process.pid(),
218 reinterpret_cast<GChildWatchFunc>(OnSetLayoutFinish),
219 this);
220 process.Release(); // do not kill the setxkbmap process on function exit.
221 }
222
223 static void OnSetLayoutFinish(GPid pid, gint status, XKeyboard* self) {
224 DLOG(INFO) << "OnSetLayoutFinish: pid=" << pid;
225 }
226
227 // The XKB layout name which we set last time like "us" and "us(dvorak)".
228 std::string current_layout_name_;
229 // The mapping of modifier keys we set last time.
230 chromeos::ModifierMap current_modifier_map_;
231
232 DISALLOW_COPY_AND_ASSIGN(XKeyboard);
233 };
234
235 } // namespace
236
237 namespace chromeos {
238
239 std::string CreateFullXkbLayoutName(const std::string& layout_name,
240 const ModifierMap& modifier_map) {
241 static const char kValidLayoutNameCharacters[] =
242 "abcdefghijklmnopqrstuvwxyz0123456789()-_";
243
244 if (layout_name.empty()) {
245 LOG(ERROR) << "Invalid layout_name: " << layout_name;
246 return "";
247 }
248
249 if (layout_name.find_first_not_of(kValidLayoutNameCharacters) !=
250 std::string::npos) {
251 LOG(ERROR) << "Invalid layout_name: " << layout_name;
252 return "";
253 }
254
255 std::string use_search_key_as_str;
256 std::string use_left_control_key_as_str;
257 std::string use_left_alt_key_as_str;
258
259 for (size_t i = 0; i < modifier_map.size(); ++i) {
260 std::string* target = NULL;
261 switch (modifier_map[i].original) {
262 case kSearchKey:
263 target = &use_search_key_as_str;
264 break;
265 case kLeftControlKey:
266 target = &use_left_control_key_as_str;
267 break;
268 case kLeftAltKey:
269 target = &use_left_alt_key_as_str;
270 break;
271 default:
272 break;
273 }
274 if (!target) {
275 LOG(ERROR) << "We don't support remaping "
276 << ModifierKeyToString(modifier_map[i].original);
277 return "";
278 }
279 if (!(target->empty())) {
280 LOG(ERROR) << ModifierKeyToString(modifier_map[i].original)
281 << " appeared twice";
282 return "";
283 }
284 *target = ModifierKeyToString(modifier_map[i].replacement);
285 }
286
287 if (use_search_key_as_str.empty() ||
288 use_left_control_key_as_str.empty() ||
289 use_left_alt_key_as_str.empty()) {
290 LOG(ERROR) << "Incomplete ModifierMap: size=" << modifier_map.size();
291 return "";
292 }
293
294 std::string full_xkb_layout_name =
295 StringPrintf("%s+chromeos(%s_%s_%s)", layout_name.c_str(),
296 use_search_key_as_str.c_str(),
297 use_left_control_key_as_str.c_str(),
298 use_left_alt_key_as_str.c_str());
299
300 if ((full_xkb_layout_name.substr(0, 3) != "us+") &&
301 (full_xkb_layout_name.substr(0, 3) != "us(")) {
302 full_xkb_layout_name += ",us";
303 }
304
305 return full_xkb_layout_name;
306 }
307
308 // This function is only for unittest.
309 bool CapsLockIsEnabled() {
310 ScopedDisplay display(XOpenDisplay(NULL));
311 if (!display.get()) {
312 return false;
313 }
314 XkbStateRec status;
315 XkbGetState(display.get(), XkbUseCoreKbd, &status);
316 return status.locked_mods & LockMask;
317 }
318
319 // TODO(yusukes): Call this function in non-UI thread or in an idle callback.
320 void SetCapsLockEnabled(bool enable_caps_lock) {
321 ScopedDisplay display(XOpenDisplay(NULL));
322 if (!display.get()) {
323 return;
324 }
325 XkbLockModifiers(
326 display.get(), XkbUseCoreKbd, LockMask, enable_caps_lock ? LockMask : 0);
327 }
328
329 bool ContainsModifierKeyAsReplacement(
330 const ModifierMap& modifier_map, ModifierKey key) {
331 for (size_t i = 0; i < modifier_map.size(); ++i) {
332 if (modifier_map[i].replacement == key) {
333 return true;
334 }
335 }
336 return false;
337 }
338
339 } // namespace chromeos
340
341
342 //
343 // licros APIs.
344 //
345 extern "C"
346 bool ChromeOSSetCurrentKeyboardLayoutByName(const std::string& layout_name) {
347 return XKeyboard::Get()->SetLayout(layout_name);
348 }
349
350 extern "C"
351 bool ChromeOSRemapModifierKeys(const chromeos::ModifierMap& modifier_map) {
352 return XKeyboard::Get()->RemapModifierKeys(modifier_map);
353 }
354
355 // TODO(yusukes): Remove this function.
356 extern "C"
357 bool ChromeOSGetAutoRepeatEnabled(bool* enabled) {
358 return XKeyboard::Get()->GetAutoRepeatEnabled(enabled);
359 }
360
361 // TODO(yusukes): We can remove this function since the default setting of the
362 // repeat mode is true, and we don't change the default.
363 extern "C"
364 bool ChromeOSSetAutoRepeatEnabled(bool enabled) {
365 return XKeyboard::Get()->SetAutoRepeatEnabled(enabled);
366 }
367
368 // TODO(yusukes): Remove this function.
369 extern "C"
370 bool ChromeOSGetAutoRepeatRate(chromeos::AutoRepeatRate* out_rate) {
371 return XKeyboard::Get()->GetAutoRepeatRate(out_rate);
372 }
373
374 extern "C"
375 bool ChromeOSSetAutoRepeatRate(const chromeos::AutoRepeatRate& rate) {
376 return XKeyboard::Get()->SetAutoRepeatRate(rate);
377 }
OLDNEW
« no previous file with comments | « chromeos_keyboard.h ('k') | chromeos_keyboard_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698