OLD | NEW |
---|---|
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 Loading... | |
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 178 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
223 // Make sure the returned value is a string. | 227 // Make sure the returned value is a string. |
224 if (actual_type == XA_STRING && actual_format == 8) | 228 if (actual_type == XA_STRING && actual_format == 8) |
225 path = reinterpret_cast<char*>(data); | 229 path = reinterpret_cast<char*>(data); |
226 | 230 |
227 XFree(data); | 231 XFree(data); |
228 XCloseDevice(dpy, dev); | 232 XCloseDevice(dpy, dev); |
229 | 233 |
230 return base::FilePath(path); | 234 return base::FilePath(path); |
231 } | 235 } |
232 | 236 |
237 // Obtain the USB-style vendor and product identifiers for an InputDevice. | |
238 // (On Linux, XI2 makes this available for all evdev devices.) | |
239 void SetDeviceIdentification(InputDevice* input_device) { | |
240 Atom product_id_atom = XInternAtom(gfx::GetXDisplay(), XI_PROP_PRODUCT_ID, 1); | |
241 uint32_t* product_info; | |
242 Atom type; | |
243 int format_return; | |
244 unsigned long num_items_return; | |
245 unsigned long bytes_after_return; | |
246 if (XIGetProperty(gfx::GetXDisplay(), input_device->id, product_id_atom, 0, 2, | |
247 0, XA_INTEGER, &type, &format_return, &num_items_return, | |
248 &bytes_after_return, | |
249 reinterpret_cast<unsigned char**>(&product_info)) == 0 && | |
250 product_info) { | |
251 input_device->vendor_id = product_info[0]; | |
252 input_device->product_id = product_info[0]; | |
253 } | |
254 } | |
sadrul
2015/04/09 01:07:43
The X11 calls in this function are happening in th
kpschoedel
2015/04/09 18:51:41
Done.
| |
255 | |
233 // Helper used to parse keyboard information. When it is done it uses | 256 // Helper used to parse keyboard information. When it is done it uses |
234 // |reply_runner| and |callback| to update the state on the UI thread. | 257 // |reply_runner| and |callback| to update the state on the UI thread. |
235 void HandleKeyboardDevicesInWorker( | 258 void HandleKeyboardDevicesInWorker( |
236 const std::vector<DeviceInfo>& device_infos, | 259 const std::vector<DeviceInfo>& device_infos, |
237 scoped_refptr<base::TaskRunner> reply_runner, | 260 scoped_refptr<base::TaskRunner> reply_runner, |
238 const KeyboardDeviceCallback& callback) { | 261 const KeyboardDeviceCallback& callback) { |
239 std::vector<KeyboardDevice> devices; | 262 std::vector<KeyboardDevice> devices; |
240 | 263 |
241 for (const DeviceInfo& device_info : device_infos) { | 264 for (const DeviceInfo& device_info : device_infos) { |
242 if (device_info.type != DEVICE_TYPE_KEYBOARD) | 265 if (device_info.type != DEVICE_TYPE_KEYBOARD) |
243 continue; | 266 continue; |
244 if (device_info.use != XISlaveKeyboard) | 267 if (device_info.use != XISlaveKeyboard) |
245 continue; // Assume all keyboards are keyboard slaves | 268 continue; // Assume all keyboards are keyboard slaves |
246 if (IsKnownInvalidKeyboardDevice(device_info.name)) | 269 if (IsKnownInvalidKeyboardDevice(device_info.name)) |
247 continue; // Skip invalid devices. | 270 continue; // Skip invalid devices. |
248 InputDeviceType type = GetInputDeviceTypeFromPath(device_info.path); | 271 InputDeviceType type = GetInputDeviceTypeFromPath(device_info.path); |
249 devices.push_back(KeyboardDevice(device_info.id, type)); | 272 KeyboardDevice keyboard(device_info.id, type, device_info.name); |
273 SetDeviceIdentification(&keyboard); | |
sadrul
2015/04/09 01:07:43
Note that we also want to collect the product/vend
kpschoedel
2015/04/09 18:51:41
Oh, joy.
| |
274 devices.push_back(keyboard); | |
250 } | 275 } |
251 | 276 |
252 reply_runner->PostTask(FROM_HERE, base::Bind(callback, devices)); | 277 reply_runner->PostTask(FROM_HERE, base::Bind(callback, devices)); |
253 } | 278 } |
254 | 279 |
255 // Helper used to parse mouse information. When it is done it uses | 280 // 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. | 281 // |reply_runner| and |callback| to update the state on the UI thread. |
257 void HandleMouseDevicesInWorker(const std::vector<DeviceInfo>& device_infos, | 282 void HandleMouseDevicesInWorker(const std::vector<DeviceInfo>& device_infos, |
258 scoped_refptr<base::TaskRunner> reply_runner, | 283 scoped_refptr<base::TaskRunner> reply_runner, |
259 const InputDeviceCallback& callback) { | 284 const InputDeviceCallback& callback) { |
260 std::vector<InputDevice> devices; | 285 std::vector<InputDevice> devices; |
261 for (const DeviceInfo& device_info : device_infos) { | 286 for (const DeviceInfo& device_info : device_infos) { |
262 if (device_info.type != DEVICE_TYPE_MOUSE || | 287 if (device_info.type != DEVICE_TYPE_MOUSE || |
263 device_info.use != XISlavePointer) { | 288 device_info.use != XISlavePointer) { |
264 continue; | 289 continue; |
265 } | 290 } |
266 | 291 |
267 InputDeviceType type = GetInputDeviceTypeFromPath(device_info.path); | 292 InputDeviceType type = GetInputDeviceTypeFromPath(device_info.path); |
268 devices.push_back(InputDevice(device_info.id, type)); | 293 devices.push_back(InputDevice(device_info.id, type, device_info.name)); |
269 } | 294 } |
270 | 295 |
271 reply_runner->PostTask(FROM_HERE, base::Bind(callback, devices)); | 296 reply_runner->PostTask(FROM_HERE, base::Bind(callback, devices)); |
272 } | 297 } |
273 | 298 |
274 // Helper used to parse touchpad information. When it is done it uses | 299 // 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. | 300 // |reply_runner| and |callback| to update the state on the UI thread. |
276 void HandleTouchpadDevicesInWorker(const std::vector<DeviceInfo>& device_infos, | 301 void HandleTouchpadDevicesInWorker(const std::vector<DeviceInfo>& device_infos, |
277 scoped_refptr<base::TaskRunner> reply_runner, | 302 scoped_refptr<base::TaskRunner> reply_runner, |
278 const InputDeviceCallback& callback) { | 303 const InputDeviceCallback& callback) { |
279 std::vector<InputDevice> devices; | 304 std::vector<InputDevice> devices; |
280 for (const DeviceInfo& device_info : device_infos) { | 305 for (const DeviceInfo& device_info : device_infos) { |
281 if (device_info.type != DEVICE_TYPE_TOUCHPAD || | 306 if (device_info.type != DEVICE_TYPE_TOUCHPAD || |
282 device_info.use != XISlavePointer) { | 307 device_info.use != XISlavePointer) { |
283 continue; | 308 continue; |
284 } | 309 } |
285 | 310 |
286 InputDeviceType type = GetInputDeviceTypeFromPath(device_info.path); | 311 InputDeviceType type = GetInputDeviceTypeFromPath(device_info.path); |
287 devices.push_back(InputDevice(device_info.id, type)); | 312 devices.push_back(InputDevice(device_info.id, type, device_info.name)); |
288 } | 313 } |
289 | 314 |
290 reply_runner->PostTask(FROM_HERE, base::Bind(callback, devices)); | 315 reply_runner->PostTask(FROM_HERE, base::Bind(callback, devices)); |
291 } | 316 } |
292 | 317 |
293 // Helper used to parse touchscreen information. When it is done it uses | 318 // 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. | 319 // |reply_runner| and |callback| to update the state on the UI thread. |
295 void HandleTouchscreenDevicesInWorker( | 320 void HandleTouchscreenDevicesInWorker( |
296 const std::vector<DeviceInfo>& device_infos, | 321 const std::vector<DeviceInfo>& device_infos, |
297 const DisplayState& display_state, | 322 const DisplayState& display_state, |
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
330 max_y = valuator.max; | 355 max_y = valuator.max; |
331 } | 356 } |
332 } | 357 } |
333 } | 358 } |
334 | 359 |
335 // Touchscreens should have absolute X and Y axes. | 360 // Touchscreens should have absolute X and Y axes. |
336 if (max_x > 0.0 && max_y > 0.0) { | 361 if (max_x > 0.0 && max_y > 0.0) { |
337 InputDeviceType type = GetInputDeviceTypeFromPath(device_info.path); | 362 InputDeviceType type = GetInputDeviceTypeFromPath(device_info.path); |
338 // |max_x| and |max_y| are inclusive values, so we need to add 1 to get | 363 // |max_x| and |max_y| are inclusive values, so we need to add 1 to get |
339 // the size. | 364 // the size. |
340 devices.push_back(TouchscreenDevice( | 365 devices.push_back( |
341 device_info.id, type, gfx::Size(max_x + 1, max_y + 1), | 366 TouchscreenDevice(device_info.id, type, device_info.name, |
342 device_info.touch_class_info.num_touches)); | 367 gfx::Size(max_x + 1, max_y + 1), |
368 device_info.touch_class_info.num_touches)); | |
343 } | 369 } |
344 } | 370 } |
345 | 371 |
346 reply_runner->PostTask(FROM_HERE, base::Bind(callback, devices)); | 372 reply_runner->PostTask(FROM_HERE, base::Bind(callback, devices)); |
347 } | 373 } |
348 | 374 |
349 // Called on a worker thread to parse the device information. | 375 // Called on a worker thread to parse the device information. |
350 void HandleHotplugEventInWorker( | 376 void HandleHotplugEventInWorker( |
351 const std::vector<DeviceInfo>& devices, | 377 const std::vector<DeviceInfo>& devices, |
352 const DisplayState& display_state, | 378 const DisplayState& display_state, |
(...skipping 96 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
449 base::WorkerPool::PostTask(FROM_HERE, | 475 base::WorkerPool::PostTask(FROM_HERE, |
450 base::Bind(&HandleHotplugEventInWorker, | 476 base::Bind(&HandleHotplugEventInWorker, |
451 device_infos, | 477 device_infos, |
452 display_state, | 478 display_state, |
453 base::ThreadTaskRunnerHandle::Get(), | 479 base::ThreadTaskRunnerHandle::Get(), |
454 callbacks), | 480 callbacks), |
455 true /* task_is_slow */); | 481 true /* task_is_slow */); |
456 } | 482 } |
457 | 483 |
458 } // namespace ui | 484 } // namespace ui |
OLD | NEW |