| 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 28 matching lines...) Expand all Loading... |
| 39 // Names of all known internal devices that should not be considered as | 39 // Names of all known internal devices that should not be considered as |
| 40 // keyboards. | 40 // keyboards. |
| 41 // TODO(rsadam@): Identify these devices using udev rules. (Crbug.com/420728.) | 41 // TODO(rsadam@): Identify these devices using udev rules. (Crbug.com/420728.) |
| 42 const char* kKnownInvalidKeyboardDeviceNames[] = {"Power Button", | 42 const char* kKnownInvalidKeyboardDeviceNames[] = {"Power Button", |
| 43 "Sleep Button", | 43 "Sleep Button", |
| 44 "Video Bus"}; | 44 "Video Bus"}; |
| 45 | 45 |
| 46 const char* kCachedAtomList[] = { | 46 const char* kCachedAtomList[] = { |
| 47 "Abs MT Position X", | 47 "Abs MT Position X", |
| 48 "Abs MT Position Y", | 48 "Abs MT Position Y", |
| 49 XI_KEYBOARD, |
| 50 XI_MOUSE, |
| 51 XI_TOUCHPAD, |
| 52 XI_TOUCHSCREEN, |
| 49 NULL, | 53 NULL, |
| 50 }; | 54 }; |
| 51 | 55 |
| 56 enum DeviceType { |
| 57 DEVICE_TYPE_KEYBOARD, |
| 58 DEVICE_TYPE_MOUSE, |
| 59 DEVICE_TYPE_TOUCHPAD, |
| 60 DEVICE_TYPE_TOUCHSCREEN, |
| 61 DEVICE_TYPE_OTHER |
| 62 }; |
| 63 |
| 52 typedef base::Callback<void(const std::vector<KeyboardDevice>&)> | 64 typedef base::Callback<void(const std::vector<KeyboardDevice>&)> |
| 53 KeyboardDeviceCallback; | 65 KeyboardDeviceCallback; |
| 54 | 66 |
| 55 typedef base::Callback<void(const std::vector<TouchscreenDevice>&)> | 67 typedef base::Callback<void(const std::vector<TouchscreenDevice>&)> |
| 56 TouchscreenDeviceCallback; | 68 TouchscreenDeviceCallback; |
| 57 | 69 |
| 70 typedef base::Callback<void(const std::vector<InputDevice>&)> |
| 71 InputDeviceCallback; |
| 72 |
| 58 // Used for updating the state on the UI thread once device information is | 73 // Used for updating the state on the UI thread once device information is |
| 59 // parsed on helper threads. | 74 // parsed on helper threads. |
| 60 struct UiCallbacks { | 75 struct UiCallbacks { |
| 61 KeyboardDeviceCallback keyboard_callback; | 76 KeyboardDeviceCallback keyboard_callback; |
| 62 TouchscreenDeviceCallback touchscreen_callback; | 77 TouchscreenDeviceCallback touchscreen_callback; |
| 78 InputDeviceCallback mouse_callback; |
| 79 InputDeviceCallback touchpad_callback; |
| 63 }; | 80 }; |
| 64 | 81 |
| 65 // Stores a copy of the XIValuatorClassInfo values so X11 device processing can | 82 // Stores a copy of the XIValuatorClassInfo values so X11 device processing can |
| 66 // happen on a worker thread. This is needed since X11 structs are not copyable. | 83 // happen on a worker thread. This is needed since X11 structs are not copyable. |
| 67 struct ValuatorClassInfo { | 84 struct ValuatorClassInfo { |
| 68 ValuatorClassInfo(const XIValuatorClassInfo& info) | 85 ValuatorClassInfo(const XIValuatorClassInfo& info) |
| 69 : label(info.label), | 86 : label(info.label), |
| 70 max(info.max), | 87 max(info.max), |
| 71 min(info.min), | 88 min(info.min), |
| 72 mode(info.mode), | 89 mode(info.mode), |
| (...skipping 12 matching lines...) Expand all Loading... |
| 85 TouchClassInfo() : mode(0), num_touches(0) {} | 102 TouchClassInfo() : mode(0), num_touches(0) {} |
| 86 | 103 |
| 87 explicit TouchClassInfo(const XITouchClassInfo& info) | 104 explicit TouchClassInfo(const XITouchClassInfo& info) |
| 88 : mode(info.mode), num_touches(info.num_touches) {} | 105 : mode(info.mode), num_touches(info.num_touches) {} |
| 89 | 106 |
| 90 int mode; | 107 int mode; |
| 91 int num_touches; | 108 int num_touches; |
| 92 }; | 109 }; |
| 93 | 110 |
| 94 struct DeviceInfo { | 111 struct DeviceInfo { |
| 95 DeviceInfo(const XIDeviceInfo& device, const base::FilePath& path) | 112 DeviceInfo(const XIDeviceInfo& device, |
| 113 DeviceType type, |
| 114 const base::FilePath& path) |
| 96 : id(device.deviceid), | 115 : id(device.deviceid), |
| 97 name(device.name), | 116 name(device.name), |
| 98 use(device.use), | 117 use(device.use), |
| 99 enabled(device.enabled), | 118 type(type), |
| 100 path(path) { | 119 path(path) { |
| 101 for (int i = 0; i < device.num_classes; ++i) { | 120 for (int i = 0; i < device.num_classes; ++i) { |
| 102 switch (device.classes[i]->type) { | 121 switch (device.classes[i]->type) { |
| 103 case XIValuatorClass: | 122 case XIValuatorClass: |
| 104 valuator_class_infos.push_back(ValuatorClassInfo( | 123 valuator_class_infos.push_back(ValuatorClassInfo( |
| 105 *reinterpret_cast<XIValuatorClassInfo*>(device.classes[i]))); | 124 *reinterpret_cast<XIValuatorClassInfo*>(device.classes[i]))); |
| 106 break; | 125 break; |
| 107 case XITouchClass: | 126 case XITouchClass: |
| 108 // A device can have at most one XITouchClassInfo. Ref: | 127 // A device can have at most one XITouchClassInfo. Ref: |
| 109 // http://manpages.ubuntu.com/manpages/saucy/man3/XIQueryDevice.3.html | 128 // http://manpages.ubuntu.com/manpages/saucy/man3/XIQueryDevice.3.html |
| 110 DCHECK(!touch_class_info.mode); | 129 DCHECK(!touch_class_info.mode); |
| 111 touch_class_info = TouchClassInfo( | 130 touch_class_info = TouchClassInfo( |
| 112 *reinterpret_cast<XITouchClassInfo*>(device.classes[i])); | 131 *reinterpret_cast<XITouchClassInfo*>(device.classes[i])); |
| 113 break; | 132 break; |
| 114 default: | 133 default: |
| 115 break; | 134 break; |
| 116 } | 135 } |
| 117 } | 136 } |
| 118 } | 137 } |
| 119 | 138 |
| 120 // Unique device identifier. | 139 // Unique device identifier. |
| 121 int id; | 140 int id; |
| 122 | 141 |
| 123 // Internal device name. | 142 // Internal device name. |
| 124 std::string name; | 143 std::string name; |
| 125 | 144 |
| 126 // Device type (ie: XIMasterPointer) | 145 // Device type (ie: XIMasterPointer) |
| 127 int use; | 146 int use; |
| 128 | 147 |
| 129 // Specifies if the device is enabled and can send events. | 148 // Specifies the type of the device. |
| 130 bool enabled; | 149 DeviceType type; |
| 131 | 150 |
| 132 // Path to the actual device (ie: /dev/input/eventXX) | 151 // Path to the actual device (ie: /dev/input/eventXX) |
| 133 base::FilePath path; | 152 base::FilePath path; |
| 134 | 153 |
| 135 std::vector<ValuatorClassInfo> valuator_class_infos; | 154 std::vector<ValuatorClassInfo> valuator_class_infos; |
| 136 | 155 |
| 137 TouchClassInfo touch_class_info; | 156 TouchClassInfo touch_class_info; |
| 138 }; | 157 }; |
| 139 | 158 |
| 140 // X11 display cache used on worker threads. This is filled on the UI thread and | 159 // X11 display cache used on worker threads. This is filled on the UI thread and |
| 141 // passed in to the worker threads. | 160 // passed in to the worker threads. |
| 142 struct DisplayState { | 161 struct DisplayState { |
| 143 Atom mt_position_x; | 162 Atom mt_position_x; |
| 144 Atom mt_position_y; | 163 Atom mt_position_y; |
| 145 }; | 164 }; |
| 146 | 165 |
| 147 // Returns true if |name| is the name of a known invalid keyboard device. Note, | 166 // Returns true if |name| is the name of a known invalid keyboard device. Note, |
| 148 // this may return false negatives. | 167 // this may return false negatives. |
| 149 bool IsKnownInvalidKeyboardDevice(const std::string& name) { | 168 bool IsKnownInvalidKeyboardDevice(const std::string& name) { |
| 169 std::string trimmed(name); |
| 170 base::TrimWhitespaceASCII(name, base::TRIM_TRAILING, &trimmed); |
| 150 for (const char* device_name : kKnownInvalidKeyboardDeviceNames) { | 171 for (const char* device_name : kKnownInvalidKeyboardDeviceNames) { |
| 151 if (name == device_name) | 172 if (trimmed == device_name) |
| 152 return true; | 173 return true; |
| 153 } | 174 } |
| 154 return false; | 175 return false; |
| 155 } | 176 } |
| 156 | 177 |
| 157 // Returns true if |name| is the name of a known XTEST device. Note, this may | 178 // Returns true if |name| is the name of a known XTEST device. Note, this may |
| 158 // return false negatives. | 179 // return false negatives. |
| 159 bool IsTestKeyboard(const std::string& name) { | 180 bool IsTestDevice(const std::string& name) { |
| 160 return name.find("XTEST") != std::string::npos; | 181 return name.find("XTEST") != std::string::npos; |
| 161 } | 182 } |
| 162 | 183 |
| 163 base::FilePath GetDevicePath(XDisplay* dpy, const XIDeviceInfo& device) { | 184 base::FilePath GetDevicePath(XDisplay* dpy, const XIDeviceInfo& device) { |
| 164 // Skip the main pointer and keyboard since XOpenDevice() generates a | 185 // Skip the main pointer and keyboard since XOpenDevice() generates a |
| 165 // BadDevice error when passed these devices. | 186 // BadDevice error when passed these devices. |
| 166 if (device.use == XIMasterPointer || device.use == XIMasterKeyboard) | 187 if (device.use == XIMasterPointer || device.use == XIMasterKeyboard) |
| 167 return base::FilePath(); | 188 return base::FilePath(); |
| 168 | 189 |
| 169 // Input device has a property "Device Node" pointing to its dev input node, | 190 // Input device has a property "Device Node" pointing to its dev input node, |
| (...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 209 | 230 |
| 210 // Helper used to parse keyboard information. When it is done it uses | 231 // Helper used to parse keyboard information. When it is done it uses |
| 211 // |reply_runner| and |callback| to update the state on the UI thread. | 232 // |reply_runner| and |callback| to update the state on the UI thread. |
| 212 void HandleKeyboardDevicesInWorker( | 233 void HandleKeyboardDevicesInWorker( |
| 213 const std::vector<DeviceInfo>& device_infos, | 234 const std::vector<DeviceInfo>& device_infos, |
| 214 scoped_refptr<base::TaskRunner> reply_runner, | 235 scoped_refptr<base::TaskRunner> reply_runner, |
| 215 const KeyboardDeviceCallback& callback) { | 236 const KeyboardDeviceCallback& callback) { |
| 216 std::vector<KeyboardDevice> devices; | 237 std::vector<KeyboardDevice> devices; |
| 217 | 238 |
| 218 for (const DeviceInfo& device_info : device_infos) { | 239 for (const DeviceInfo& device_info : device_infos) { |
| 219 if (!device_info.enabled || device_info.use != XISlaveKeyboard) | 240 if (device_info.type != DEVICE_TYPE_KEYBOARD) |
| 241 continue; |
| 242 if (device_info.use != XISlaveKeyboard) |
| 220 continue; // Assume all keyboards are keyboard slaves | 243 continue; // Assume all keyboards are keyboard slaves |
| 221 std::string device_name(device_info.name); | 244 if (IsKnownInvalidKeyboardDevice(device_info.name)) |
| 222 base::TrimWhitespaceASCII(device_name, base::TRIM_TRAILING, &device_name); | |
| 223 if (IsTestKeyboard(device_name)) | |
| 224 continue; // Skip test devices. | |
| 225 if (IsKnownInvalidKeyboardDevice(device_name)) | |
| 226 continue; // Skip invalid devices. | 245 continue; // Skip invalid devices. |
| 227 InputDeviceType type = GetInputDeviceTypeFromPath(device_info.path); | 246 InputDeviceType type = GetInputDeviceTypeFromPath(device_info.path); |
| 228 devices.push_back(KeyboardDevice(device_info.id, type)); | 247 devices.push_back(KeyboardDevice(device_info.id, type)); |
| 229 } | 248 } |
| 230 | 249 |
| 231 reply_runner->PostTask(FROM_HERE, base::Bind(callback, devices)); | 250 reply_runner->PostTask(FROM_HERE, base::Bind(callback, devices)); |
| 232 } | 251 } |
| 233 | 252 |
| 253 // Helper used to parse mouse information. When it is done it uses |
| 254 // |reply_runner| and |callback| to update the state on the UI thread. |
| 255 void HandleMouseDevicesInWorker(const std::vector<DeviceInfo>& device_infos, |
| 256 scoped_refptr<base::TaskRunner> reply_runner, |
| 257 const InputDeviceCallback& callback) { |
| 258 std::vector<InputDevice> devices; |
| 259 for (const DeviceInfo& device_info : device_infos) { |
| 260 if (device_info.type != DEVICE_TYPE_MOUSE || |
| 261 device_info.use != XISlavePointer) { |
| 262 continue; |
| 263 } |
| 264 |
| 265 InputDeviceType type = GetInputDeviceTypeFromPath(device_info.path); |
| 266 devices.push_back(InputDevice(device_info.id, type)); |
| 267 } |
| 268 |
| 269 reply_runner->PostTask(FROM_HERE, base::Bind(callback, devices)); |
| 270 } |
| 271 |
| 272 // Helper used to parse touchpad information. When it is done it uses |
| 273 // |reply_runner| and |callback| to update the state on the UI thread. |
| 274 void HandleTouchpadDevicesInWorker(const std::vector<DeviceInfo>& device_infos, |
| 275 scoped_refptr<base::TaskRunner> reply_runner, |
| 276 const InputDeviceCallback& callback) { |
| 277 std::vector<InputDevice> devices; |
| 278 for (const DeviceInfo& device_info : device_infos) { |
| 279 if (device_info.type != DEVICE_TYPE_TOUCHPAD || |
| 280 device_info.use != XISlavePointer) { |
| 281 continue; |
| 282 } |
| 283 |
| 284 InputDeviceType type = GetInputDeviceTypeFromPath(device_info.path); |
| 285 devices.push_back(InputDevice(device_info.id, type)); |
| 286 } |
| 287 |
| 288 reply_runner->PostTask(FROM_HERE, base::Bind(callback, devices)); |
| 289 } |
| 290 |
| 234 // Helper used to parse touchscreen information. When it is done it uses | 291 // Helper used to parse touchscreen information. When it is done it uses |
| 235 // |reply_runner| and |callback| to update the state on the UI thread. | 292 // |reply_runner| and |callback| to update the state on the UI thread. |
| 236 void HandleTouchscreenDevicesInWorker( | 293 void HandleTouchscreenDevicesInWorker( |
| 237 const std::vector<DeviceInfo>& device_infos, | 294 const std::vector<DeviceInfo>& device_infos, |
| 238 const DisplayState& display_state, | 295 const DisplayState& display_state, |
| 239 scoped_refptr<base::TaskRunner> reply_runner, | 296 scoped_refptr<base::TaskRunner> reply_runner, |
| 240 const TouchscreenDeviceCallback& callback) { | 297 const TouchscreenDeviceCallback& callback) { |
| 241 std::vector<TouchscreenDevice> devices; | 298 std::vector<TouchscreenDevice> devices; |
| 242 if (display_state.mt_position_x == None || | 299 if (display_state.mt_position_x == None || |
| 243 display_state.mt_position_y == None) | 300 display_state.mt_position_y == None) |
| 244 return; | 301 return; |
| 245 | 302 |
| 246 std::set<int> no_match_touchscreen; | |
| 247 for (const DeviceInfo& device_info : device_infos) { | 303 for (const DeviceInfo& device_info : device_infos) { |
| 248 if (!device_info.enabled || (device_info.use != XIFloatingSlave | 304 if (device_info.type != DEVICE_TYPE_TOUCHSCREEN || |
| 249 && device_info.use != XISlavePointer)) | 305 (device_info.use != XIFloatingSlave && |
| 306 device_info.use != XISlavePointer)) { |
| 307 continue; |
| 308 } |
| 309 |
| 310 // Touchscreens should be direct touch devices. |
| 311 if (device_info.touch_class_info.mode != XIDirectTouch) |
| 250 continue; | 312 continue; |
| 251 | 313 |
| 252 double max_x = -1.0; | 314 double max_x = -1.0; |
| 253 double max_y = -1.0; | 315 double max_y = -1.0; |
| 254 bool is_direct_touch = false; | |
| 255 | 316 |
| 256 for (const ValuatorClassInfo& valuator : device_info.valuator_class_infos) { | 317 for (const ValuatorClassInfo& valuator : device_info.valuator_class_infos) { |
| 257 if (display_state.mt_position_x == valuator.label) { | 318 if (display_state.mt_position_x == valuator.label) { |
| 258 // Ignore X axis valuator with unexpected properties | 319 // Ignore X axis valuator with unexpected properties |
| 259 if (valuator.number == 0 && valuator.mode == Absolute && | 320 if (valuator.number == 0 && valuator.mode == Absolute && |
| 260 valuator.min == 0.0) { | 321 valuator.min == 0.0) { |
| 261 max_x = valuator.max; | 322 max_x = valuator.max; |
| 262 } | 323 } |
| 263 } else if (display_state.mt_position_y == valuator.label) { | 324 } else if (display_state.mt_position_y == valuator.label) { |
| 264 // Ignore Y axis valuator with unexpected properties | 325 // Ignore Y axis valuator with unexpected properties |
| 265 if (valuator.number == 1 && valuator.mode == Absolute && | 326 if (valuator.number == 1 && valuator.mode == Absolute && |
| 266 valuator.min == 0.0) { | 327 valuator.min == 0.0) { |
| 267 max_y = valuator.max; | 328 max_y = valuator.max; |
| 268 } | 329 } |
| 269 } | 330 } |
| 270 } | 331 } |
| 271 | 332 |
| 272 if (device_info.touch_class_info.mode) | 333 // Touchscreens should have absolute X and Y axes. |
| 273 is_direct_touch = device_info.touch_class_info.mode == XIDirectTouch; | 334 if (max_x > 0.0 && max_y > 0.0) { |
| 274 | |
| 275 // Touchscreens should have absolute X and Y axes, and be direct touch | |
| 276 // devices. | |
| 277 if (max_x > 0.0 && max_y > 0.0 && is_direct_touch) { | |
| 278 InputDeviceType type = GetInputDeviceTypeFromPath(device_info.path); | 335 InputDeviceType type = GetInputDeviceTypeFromPath(device_info.path); |
| 279 // |max_x| and |max_y| are inclusive values, so we need to add 1 to get | 336 // |max_x| and |max_y| are inclusive values, so we need to add 1 to get |
| 280 // the size. | 337 // the size. |
| 281 devices.push_back(TouchscreenDevice( | 338 devices.push_back(TouchscreenDevice( |
| 282 device_info.id, type, gfx::Size(max_x + 1, max_y + 1), | 339 device_info.id, type, gfx::Size(max_x + 1, max_y + 1), |
| 283 device_info.touch_class_info.num_touches)); | 340 device_info.touch_class_info.num_touches)); |
| 284 } | 341 } |
| 285 } | 342 } |
| 286 | 343 |
| 287 reply_runner->PostTask(FROM_HERE, base::Bind(callback, devices)); | 344 reply_runner->PostTask(FROM_HERE, base::Bind(callback, devices)); |
| 288 } | 345 } |
| 289 | 346 |
| 290 // Called on a worker thread to parse the device information. | 347 // Called on a worker thread to parse the device information. |
| 291 void HandleHotplugEventInWorker( | 348 void HandleHotplugEventInWorker( |
| 292 const std::vector<DeviceInfo>& devices, | 349 const std::vector<DeviceInfo>& devices, |
| 293 const DisplayState& display_state, | 350 const DisplayState& display_state, |
| 294 scoped_refptr<base::TaskRunner> reply_runner, | 351 scoped_refptr<base::TaskRunner> reply_runner, |
| 295 const UiCallbacks& callbacks) { | 352 const UiCallbacks& callbacks) { |
| 296 HandleTouchscreenDevicesInWorker( | 353 HandleTouchscreenDevicesInWorker( |
| 297 devices, display_state, reply_runner, callbacks.touchscreen_callback); | 354 devices, display_state, reply_runner, callbacks.touchscreen_callback); |
| 298 HandleKeyboardDevicesInWorker( | 355 HandleKeyboardDevicesInWorker( |
| 299 devices, reply_runner, callbacks.keyboard_callback); | 356 devices, reply_runner, callbacks.keyboard_callback); |
| 357 HandleMouseDevicesInWorker(devices, reply_runner, callbacks.mouse_callback); |
| 358 HandleTouchpadDevicesInWorker(devices, reply_runner, |
| 359 callbacks.touchpad_callback); |
| 300 } | 360 } |
| 301 | 361 |
| 302 DeviceHotplugEventObserver* GetHotplugEventObserver() { | 362 DeviceHotplugEventObserver* GetHotplugEventObserver() { |
| 303 return DeviceDataManager::GetInstance(); | 363 return DeviceDataManager::GetInstance(); |
| 304 } | 364 } |
| 305 | 365 |
| 306 void OnKeyboardDevices(const std::vector<KeyboardDevice>& devices) { | 366 void OnKeyboardDevices(const std::vector<KeyboardDevice>& devices) { |
| 307 GetHotplugEventObserver()->OnKeyboardDevicesUpdated(devices); | 367 GetHotplugEventObserver()->OnKeyboardDevicesUpdated(devices); |
| 308 } | 368 } |
| 309 | 369 |
| 310 void OnTouchscreenDevices(const std::vector<TouchscreenDevice>& devices) { | 370 void OnTouchscreenDevices(const std::vector<TouchscreenDevice>& devices) { |
| 311 GetHotplugEventObserver()->OnTouchscreenDevicesUpdated(devices); | 371 GetHotplugEventObserver()->OnTouchscreenDevicesUpdated(devices); |
| 312 } | 372 } |
| 313 | 373 |
| 374 void OnMouseDevices(const std::vector<InputDevice>& devices) { |
| 375 GetHotplugEventObserver()->OnMouseDevicesUpdated(devices); |
| 376 } |
| 377 |
| 378 void OnTouchpadDevices(const std::vector<InputDevice>& devices) { |
| 379 GetHotplugEventObserver()->OnTouchpadDevicesUpdated(devices); |
| 380 } |
| 381 |
| 314 } // namespace | 382 } // namespace |
| 315 | 383 |
| 316 X11HotplugEventHandler::X11HotplugEventHandler() | 384 X11HotplugEventHandler::X11HotplugEventHandler() |
| 317 : atom_cache_(gfx::GetXDisplay(), kCachedAtomList) { | 385 : atom_cache_(gfx::GetXDisplay(), kCachedAtomList) { |
| 318 } | 386 } |
| 319 | 387 |
| 320 X11HotplugEventHandler::~X11HotplugEventHandler() { | 388 X11HotplugEventHandler::~X11HotplugEventHandler() { |
| 321 } | 389 } |
| 322 | 390 |
| 323 void X11HotplugEventHandler::OnHotplugEvent() { | 391 void X11HotplugEventHandler::OnHotplugEvent() { |
| 324 const XIDeviceList& device_list = | |
| 325 DeviceListCacheX11::GetInstance()->GetXI2DeviceList(gfx::GetXDisplay()); | |
| 326 Display* display = gfx::GetXDisplay(); | 392 Display* display = gfx::GetXDisplay(); |
| 393 const XDeviceList& device_list_xi = |
| 394 DeviceListCacheX11::GetInstance()->GetXDeviceList(display); |
| 395 const XIDeviceList& device_list_xi2 = |
| 396 DeviceListCacheX11::GetInstance()->GetXI2DeviceList(display); |
| 397 |
| 398 const int kMaxDeviceNum = 128; |
| 399 DeviceType device_types[kMaxDeviceNum]; |
| 400 for (int i = 0; i < kMaxDeviceNum; ++i) |
| 401 device_types[i] = DEVICE_TYPE_OTHER; |
| 402 |
| 403 for (int i = 0; i < device_list_xi.count; ++i) { |
| 404 int id = device_list_xi[i].id; |
| 405 if (id >= kMaxDeviceNum) |
| 406 continue; |
| 407 |
| 408 Atom type = device_list_xi[i].type; |
| 409 if (type == atom_cache_.GetAtom(XI_KEYBOARD)) |
| 410 device_types[id] = DEVICE_TYPE_KEYBOARD; |
| 411 else if (type == atom_cache_.GetAtom(XI_MOUSE)) |
| 412 device_types[id] = DEVICE_TYPE_MOUSE; |
| 413 else if (type == atom_cache_.GetAtom(XI_TOUCHPAD)) |
| 414 device_types[id] = DEVICE_TYPE_TOUCHPAD; |
| 415 else if (type == atom_cache_.GetAtom(XI_TOUCHSCREEN)) |
| 416 device_types[id] = DEVICE_TYPE_TOUCHSCREEN; |
| 417 } |
| 327 | 418 |
| 328 std::vector<DeviceInfo> device_infos; | 419 std::vector<DeviceInfo> device_infos; |
| 329 for (int i = 0; i < device_list.count; ++i) { | 420 for (int i = 0; i < device_list_xi2.count; ++i) { |
| 330 const XIDeviceInfo& device = device_list[i]; | 421 const XIDeviceInfo& device = device_list_xi2[i]; |
| 331 device_infos.push_back(DeviceInfo(device, GetDevicePath(display, device))); | 422 if (!device.enabled || IsTestDevice(device.name)) |
| 423 continue; |
| 424 |
| 425 DeviceType device_type = (device.deviceid < kMaxDeviceNum) |
| 426 ? device_types[device.deviceid] |
| 427 : DEVICE_TYPE_OTHER; |
| 428 device_infos.push_back( |
| 429 DeviceInfo(device, device_type, GetDevicePath(display, device))); |
| 332 } | 430 } |
| 333 | 431 |
| 334 // X11 is not thread safe, so first get all the required state. | 432 // X11 is not thread safe, so first get all the required state. |
| 335 DisplayState display_state; | 433 DisplayState display_state; |
| 336 display_state.mt_position_x = atom_cache_.GetAtom("Abs MT Position X"); | 434 display_state.mt_position_x = atom_cache_.GetAtom("Abs MT Position X"); |
| 337 display_state.mt_position_y = atom_cache_.GetAtom("Abs MT Position Y"); | 435 display_state.mt_position_y = atom_cache_.GetAtom("Abs MT Position Y"); |
| 338 | 436 |
| 339 UiCallbacks callbacks; | 437 UiCallbacks callbacks; |
| 340 callbacks.keyboard_callback = base::Bind(&OnKeyboardDevices); | 438 callbacks.keyboard_callback = base::Bind(&OnKeyboardDevices); |
| 341 callbacks.touchscreen_callback = base::Bind(&OnTouchscreenDevices); | 439 callbacks.touchscreen_callback = base::Bind(&OnTouchscreenDevices); |
| 342 // TODO(pkotwicz): Compute the lists of mice and touchpads and send the new | 440 callbacks.mouse_callback = base::Bind(&OnMouseDevices); |
| 343 // lists to DeviceHotplugEventObserver. | 441 callbacks.touchpad_callback = base::Bind(&OnTouchpadDevices); |
| 344 | 442 |
| 345 // Parsing the device information may block, so delegate the operation to a | 443 // Parsing the device information may block, so delegate the operation to a |
| 346 // worker thread. Once the device information is extracted the parsed devices | 444 // worker thread. Once the device information is extracted the parsed devices |
| 347 // will be returned via the callbacks. | 445 // will be returned via the callbacks. |
| 348 base::WorkerPool::PostTask(FROM_HERE, | 446 base::WorkerPool::PostTask(FROM_HERE, |
| 349 base::Bind(&HandleHotplugEventInWorker, | 447 base::Bind(&HandleHotplugEventInWorker, |
| 350 device_infos, | 448 device_infos, |
| 351 display_state, | 449 display_state, |
| 352 base::ThreadTaskRunnerHandle::Get(), | 450 base::ThreadTaskRunnerHandle::Get(), |
| 353 callbacks), | 451 callbacks), |
| 354 true /* task_is_slow */); | 452 true /* task_is_slow */); |
| 355 } | 453 } |
| 356 | 454 |
| 357 } // namespace ui | 455 } // namespace ui |
| OLD | NEW |