Chromium Code Reviews| 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 |