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

Side by Side Diff: ui/events/platform/x11/x11_hotplug_event_handler.cc

Issue 1073573002: Ozone support for device special cases in keyboard event rewriting. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: address review comments Created 5 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
« no previous file with comments | « ui/events/ozone/evdev/touch_event_converter_evdev_unittest.cc ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright 2014 The Chromium Authors. All rights reserved. 1 // Copyright 2014 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "ui/events/platform/x11/x11_hotplug_event_handler.h" 5 #include "ui/events/platform/x11/x11_hotplug_event_handler.h"
6 6
7 #include <X11/Xatom.h> 7 #include <X11/Xatom.h>
8 #include <X11/extensions/XInput.h> 8 #include <X11/extensions/XInput.h>
9 #include <X11/extensions/XInput2.h> 9 #include <X11/extensions/XInput2.h>
10 10
(...skipping 14 matching lines...) Expand all
25 #include "base/thread_task_runner_handle.h" 25 #include "base/thread_task_runner_handle.h"
26 #include "base/threading/worker_pool.h" 26 #include "base/threading/worker_pool.h"
27 #include "ui/events/devices/device_data_manager.h" 27 #include "ui/events/devices/device_data_manager.h"
28 #include "ui/events/devices/device_hotplug_event_observer.h" 28 #include "ui/events/devices/device_hotplug_event_observer.h"
29 #include "ui/events/devices/device_util_linux.h" 29 #include "ui/events/devices/device_util_linux.h"
30 #include "ui/events/devices/input_device.h" 30 #include "ui/events/devices/input_device.h"
31 #include "ui/events/devices/keyboard_device.h" 31 #include "ui/events/devices/keyboard_device.h"
32 #include "ui/events/devices/touchscreen_device.h" 32 #include "ui/events/devices/touchscreen_device.h"
33 #include "ui/gfx/x/x11_types.h" 33 #include "ui/gfx/x/x11_types.h"
34 34
35 #ifndef XI_PROP_PRODUCT_ID
36 #define XI_PROP_PRODUCT_ID "Device Product ID"
37 #endif
38
35 namespace ui { 39 namespace ui {
36 40
37 namespace { 41 namespace {
38 42
39 // Names of all known internal devices that should not be considered as 43 // Names of all known internal devices that should not be considered as
40 // keyboards. 44 // keyboards.
41 // TODO(rsadam@): Identify these devices using udev rules. (Crbug.com/420728.) 45 // TODO(rsadam@): Identify these devices using udev rules. (Crbug.com/420728.)
42 const char* kKnownInvalidKeyboardDeviceNames[] = {"Power Button", 46 const char* kKnownInvalidKeyboardDeviceNames[] = {"Power Button",
43 "Sleep Button", 47 "Sleep Button",
44 "Video Bus", 48 "Video Bus",
(...skipping 61 matching lines...) Expand 10 before | Expand all | Expand 10 after
106 explicit TouchClassInfo(const XITouchClassInfo& info) 110 explicit TouchClassInfo(const XITouchClassInfo& info)
107 : mode(info.mode), num_touches(info.num_touches) {} 111 : mode(info.mode), num_touches(info.num_touches) {}
108 112
109 int mode; 113 int mode;
110 int num_touches; 114 int num_touches;
111 }; 115 };
112 116
113 struct DeviceInfo { 117 struct DeviceInfo {
114 DeviceInfo(const XIDeviceInfo& device, 118 DeviceInfo(const XIDeviceInfo& device,
115 DeviceType type, 119 DeviceType type,
116 const base::FilePath& path) 120 const base::FilePath& path,
121 uint16_t vendor,
122 uint16_t product)
117 : id(device.deviceid), 123 : id(device.deviceid),
118 name(device.name), 124 name(device.name),
125 vendor_id(vendor),
126 product_id(product),
119 use(device.use), 127 use(device.use),
120 type(type), 128 type(type),
121 path(path) { 129 path(path) {
122 for (int i = 0; i < device.num_classes; ++i) { 130 for (int i = 0; i < device.num_classes; ++i) {
123 switch (device.classes[i]->type) { 131 switch (device.classes[i]->type) {
124 case XIValuatorClass: 132 case XIValuatorClass:
125 valuator_class_infos.push_back(ValuatorClassInfo( 133 valuator_class_infos.push_back(ValuatorClassInfo(
126 *reinterpret_cast<XIValuatorClassInfo*>(device.classes[i]))); 134 *reinterpret_cast<XIValuatorClassInfo*>(device.classes[i])));
127 break; 135 break;
128 case XITouchClass: 136 case XITouchClass:
129 // A device can have at most one XITouchClassInfo. Ref: 137 // A device can have at most one XITouchClassInfo. Ref:
130 // http://manpages.ubuntu.com/manpages/saucy/man3/XIQueryDevice.3.html 138 // http://manpages.ubuntu.com/manpages/saucy/man3/XIQueryDevice.3.html
131 DCHECK(!touch_class_info.mode); 139 DCHECK(!touch_class_info.mode);
132 touch_class_info = TouchClassInfo( 140 touch_class_info = TouchClassInfo(
133 *reinterpret_cast<XITouchClassInfo*>(device.classes[i])); 141 *reinterpret_cast<XITouchClassInfo*>(device.classes[i]));
134 break; 142 break;
135 default: 143 default:
136 break; 144 break;
137 } 145 }
138 } 146 }
139 } 147 }
140 148
141 // Unique device identifier. 149 // Unique device identifier.
142 int id; 150 int id;
143 151
144 // Internal device name. 152 // Internal device name.
145 std::string name; 153 std::string name;
146 154
155 // USB-style device identifiers.
156 uint16_t vendor_id;
157 uint16_t product_id;
158
147 // Device type (ie: XIMasterPointer) 159 // Device type (ie: XIMasterPointer)
148 int use; 160 int use;
149 161
150 // Specifies the type of the device. 162 // Specifies the type of the device.
151 DeviceType type; 163 DeviceType type;
152 164
153 // Path to the actual device (ie: /dev/input/eventXX) 165 // Path to the actual device (ie: /dev/input/eventXX)
154 base::FilePath path; 166 base::FilePath path;
155 167
156 std::vector<ValuatorClassInfo> valuator_class_infos; 168 std::vector<ValuatorClassInfo> valuator_class_infos;
(...skipping 82 matching lines...) Expand 10 before | Expand all | Expand 10 after
239 std::vector<KeyboardDevice> devices; 251 std::vector<KeyboardDevice> devices;
240 252
241 for (const DeviceInfo& device_info : device_infos) { 253 for (const DeviceInfo& device_info : device_infos) {
242 if (device_info.type != DEVICE_TYPE_KEYBOARD) 254 if (device_info.type != DEVICE_TYPE_KEYBOARD)
243 continue; 255 continue;
244 if (device_info.use != XISlaveKeyboard) 256 if (device_info.use != XISlaveKeyboard)
245 continue; // Assume all keyboards are keyboard slaves 257 continue; // Assume all keyboards are keyboard slaves
246 if (IsKnownInvalidKeyboardDevice(device_info.name)) 258 if (IsKnownInvalidKeyboardDevice(device_info.name))
247 continue; // Skip invalid devices. 259 continue; // Skip invalid devices.
248 InputDeviceType type = GetInputDeviceTypeFromPath(device_info.path); 260 InputDeviceType type = GetInputDeviceTypeFromPath(device_info.path);
249 devices.push_back(KeyboardDevice(device_info.id, type)); 261 KeyboardDevice keyboard(device_info.id, type, device_info.name);
262 devices.push_back(keyboard);
250 } 263 }
251 264
252 reply_runner->PostTask(FROM_HERE, base::Bind(callback, devices)); 265 reply_runner->PostTask(FROM_HERE, base::Bind(callback, devices));
253 } 266 }
254 267
255 // Helper used to parse mouse information. When it is done it uses 268 // Helper used to parse mouse information. When it is done it uses
256 // |reply_runner| and |callback| to update the state on the UI thread. 269 // |reply_runner| and |callback| to update the state on the UI thread.
257 void HandleMouseDevicesInWorker(const std::vector<DeviceInfo>& device_infos, 270 void HandleMouseDevicesInWorker(const std::vector<DeviceInfo>& device_infos,
258 scoped_refptr<base::TaskRunner> reply_runner, 271 scoped_refptr<base::TaskRunner> reply_runner,
259 const InputDeviceCallback& callback) { 272 const InputDeviceCallback& callback) {
260 std::vector<InputDevice> devices; 273 std::vector<InputDevice> devices;
261 for (const DeviceInfo& device_info : device_infos) { 274 for (const DeviceInfo& device_info : device_infos) {
262 if (device_info.type != DEVICE_TYPE_MOUSE || 275 if (device_info.type != DEVICE_TYPE_MOUSE ||
263 device_info.use != XISlavePointer) { 276 device_info.use != XISlavePointer) {
264 continue; 277 continue;
265 } 278 }
266 279
267 InputDeviceType type = GetInputDeviceTypeFromPath(device_info.path); 280 InputDeviceType type = GetInputDeviceTypeFromPath(device_info.path);
268 devices.push_back(InputDevice(device_info.id, type)); 281 devices.push_back(InputDevice(device_info.id, type, device_info.name));
269 } 282 }
270 283
271 reply_runner->PostTask(FROM_HERE, base::Bind(callback, devices)); 284 reply_runner->PostTask(FROM_HERE, base::Bind(callback, devices));
272 } 285 }
273 286
274 // Helper used to parse touchpad information. When it is done it uses 287 // Helper used to parse touchpad information. When it is done it uses
275 // |reply_runner| and |callback| to update the state on the UI thread. 288 // |reply_runner| and |callback| to update the state on the UI thread.
276 void HandleTouchpadDevicesInWorker(const std::vector<DeviceInfo>& device_infos, 289 void HandleTouchpadDevicesInWorker(const std::vector<DeviceInfo>& device_infos,
277 scoped_refptr<base::TaskRunner> reply_runner, 290 scoped_refptr<base::TaskRunner> reply_runner,
278 const InputDeviceCallback& callback) { 291 const InputDeviceCallback& callback) {
279 std::vector<InputDevice> devices; 292 std::vector<InputDevice> devices;
280 for (const DeviceInfo& device_info : device_infos) { 293 for (const DeviceInfo& device_info : device_infos) {
281 if (device_info.type != DEVICE_TYPE_TOUCHPAD || 294 if (device_info.type != DEVICE_TYPE_TOUCHPAD ||
282 device_info.use != XISlavePointer) { 295 device_info.use != XISlavePointer) {
283 continue; 296 continue;
284 } 297 }
285 298
286 InputDeviceType type = GetInputDeviceTypeFromPath(device_info.path); 299 InputDeviceType type = GetInputDeviceTypeFromPath(device_info.path);
287 devices.push_back(InputDevice(device_info.id, type)); 300 devices.push_back(InputDevice(device_info.id, type, device_info.name));
288 } 301 }
289 302
290 reply_runner->PostTask(FROM_HERE, base::Bind(callback, devices)); 303 reply_runner->PostTask(FROM_HERE, base::Bind(callback, devices));
291 } 304 }
292 305
293 // Helper used to parse touchscreen information. When it is done it uses 306 // Helper used to parse touchscreen information. When it is done it uses
294 // |reply_runner| and |callback| to update the state on the UI thread. 307 // |reply_runner| and |callback| to update the state on the UI thread.
295 void HandleTouchscreenDevicesInWorker( 308 void HandleTouchscreenDevicesInWorker(
296 const std::vector<DeviceInfo>& device_infos, 309 const std::vector<DeviceInfo>& device_infos,
297 const DisplayState& display_state, 310 const DisplayState& display_state,
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after
330 max_y = valuator.max; 343 max_y = valuator.max;
331 } 344 }
332 } 345 }
333 } 346 }
334 347
335 // Touchscreens should have absolute X and Y axes. 348 // Touchscreens should have absolute X and Y axes.
336 if (max_x > 0.0 && max_y > 0.0) { 349 if (max_x > 0.0 && max_y > 0.0) {
337 InputDeviceType type = GetInputDeviceTypeFromPath(device_info.path); 350 InputDeviceType type = GetInputDeviceTypeFromPath(device_info.path);
338 // |max_x| and |max_y| are inclusive values, so we need to add 1 to get 351 // |max_x| and |max_y| are inclusive values, so we need to add 1 to get
339 // the size. 352 // the size.
340 devices.push_back(TouchscreenDevice( 353 devices.push_back(
341 device_info.id, type, gfx::Size(max_x + 1, max_y + 1), 354 TouchscreenDevice(device_info.id, type, device_info.name,
342 device_info.touch_class_info.num_touches)); 355 gfx::Size(max_x + 1, max_y + 1),
356 device_info.touch_class_info.num_touches));
343 } 357 }
344 } 358 }
345 359
346 reply_runner->PostTask(FROM_HERE, base::Bind(callback, devices)); 360 reply_runner->PostTask(FROM_HERE, base::Bind(callback, devices));
347 } 361 }
348 362
349 // Called on a worker thread to parse the device information. 363 // Called on a worker thread to parse the device information.
350 void HandleHotplugEventInWorker( 364 void HandleHotplugEventInWorker(
351 const std::vector<DeviceInfo>& devices, 365 const std::vector<DeviceInfo>& devices,
352 const DisplayState& display_state, 366 const DisplayState& display_state,
(...skipping 68 matching lines...) Expand 10 before | Expand all | Expand 10 after
421 std::vector<DeviceInfo> device_infos; 435 std::vector<DeviceInfo> device_infos;
422 for (int i = 0; i < device_list_xi2.count; ++i) { 436 for (int i = 0; i < device_list_xi2.count; ++i) {
423 const XIDeviceInfo& device = device_list_xi2[i]; 437 const XIDeviceInfo& device = device_list_xi2[i];
424 if (!device.enabled || IsTestDevice(device.name)) 438 if (!device.enabled || IsTestDevice(device.name))
425 continue; 439 continue;
426 440
427 DeviceType device_type = 441 DeviceType device_type =
428 (device.deviceid >= 0 && device.deviceid < kMaxDeviceNum) 442 (device.deviceid >= 0 && device.deviceid < kMaxDeviceNum)
429 ? device_types[device.deviceid] 443 ? device_types[device.deviceid]
430 : DEVICE_TYPE_OTHER; 444 : DEVICE_TYPE_OTHER;
431 device_infos.push_back( 445
432 DeviceInfo(device, device_type, GetDevicePath(display, device))); 446 // Obtain the USB-style vendor and product identifiers.
447 // (On Linux, XI2 makes this available for all evdev devices.
448 Atom product_id_atom =
449 XInternAtom(gfx::GetXDisplay(), XI_PROP_PRODUCT_ID, 1);
sadrul 2015/04/09 20:44:29 Use atom_cache_ instead.
kpschoedel 2015/04/09 21:22:14 Done.
450 uint32_t* product_info;
451 Atom type;
452 int format_return;
453 unsigned long num_items_return;
454 unsigned long bytes_after_return;
455 uint16_t vendor = 0;
456 uint16_t product = 0;
457 if (XIGetProperty(gfx::GetXDisplay(), device.deviceid, product_id_atom, 0,
458 2, 0, XA_INTEGER, &type, &format_return,
459 &num_items_return, &bytes_after_return,
460 reinterpret_cast<unsigned char**>(&product_info)) == 0 &&
461 product_info) {
462 vendor = product_info[0];
463 product = product_info[1];
464 }
sadrul 2015/04/09 20:44:29 Whoops. I think |product_info| is leaking. XFree
kpschoedel 2015/04/09 21:22:15 Done. (It used to leak in EventRewriter, too.)
465
466 device_infos.push_back(DeviceInfo(
467 device, device_type, GetDevicePath(display, device), vendor, product));
433 } 468 }
434 469
435 // X11 is not thread safe, so first get all the required state. 470 // X11 is not thread safe, so first get all the required state.
436 DisplayState display_state; 471 DisplayState display_state;
437 display_state.mt_position_x = atom_cache_.GetAtom("Abs MT Position X"); 472 display_state.mt_position_x = atom_cache_.GetAtom("Abs MT Position X");
438 display_state.mt_position_y = atom_cache_.GetAtom("Abs MT Position Y"); 473 display_state.mt_position_y = atom_cache_.GetAtom("Abs MT Position Y");
439 474
440 UiCallbacks callbacks; 475 UiCallbacks callbacks;
441 callbacks.keyboard_callback = base::Bind(&OnKeyboardDevices); 476 callbacks.keyboard_callback = base::Bind(&OnKeyboardDevices);
442 callbacks.touchscreen_callback = base::Bind(&OnTouchscreenDevices); 477 callbacks.touchscreen_callback = base::Bind(&OnTouchscreenDevices);
443 callbacks.mouse_callback = base::Bind(&OnMouseDevices); 478 callbacks.mouse_callback = base::Bind(&OnMouseDevices);
444 callbacks.touchpad_callback = base::Bind(&OnTouchpadDevices); 479 callbacks.touchpad_callback = base::Bind(&OnTouchpadDevices);
445 480
446 // Parsing the device information may block, so delegate the operation to a 481 // Parsing the device information may block, so delegate the operation to a
447 // worker thread. Once the device information is extracted the parsed devices 482 // worker thread. Once the device information is extracted the parsed devices
448 // will be returned via the callbacks. 483 // will be returned via the callbacks.
449 base::WorkerPool::PostTask(FROM_HERE, 484 base::WorkerPool::PostTask(
450 base::Bind(&HandleHotplugEventInWorker, 485 FROM_HERE,
451 device_infos, 486 base::Bind(&HandleHotplugEventInWorker, device_infos, display_state,
452 display_state, 487 base::ThreadTaskRunnerHandle::Get(), callbacks),
453 base::ThreadTaskRunnerHandle::Get(), 488 true /* task_is_slow */);
454 callbacks),
455 true /* task_is_slow */);
456 } 489 }
457 490
458 } // namespace ui 491 } // namespace ui
OLDNEW
« no previous file with comments | « ui/events/ozone/evdev/touch_event_converter_evdev_unittest.cc ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698