Index: ui/events/platform/x11/x11_hotplug_event_handler.cc |
diff --git a/ui/events/platform/x11/x11_hotplug_event_handler.cc b/ui/events/platform/x11/x11_hotplug_event_handler.cc |
index ddd3aec61733f06b6cb41f4cd717fd40e937048c..fcac274301d25fb990151c9c7b954562645a68b2 100644 |
--- a/ui/events/platform/x11/x11_hotplug_event_handler.cc |
+++ b/ui/events/platform/x11/x11_hotplug_event_handler.cc |
@@ -46,20 +46,37 @@ const char* kKnownInvalidKeyboardDeviceNames[] = {"Power Button", |
const char* kCachedAtomList[] = { |
"Abs MT Position X", |
"Abs MT Position Y", |
+ XI_KEYBOARD, |
+ XI_MOUSE, |
+ XI_TOUCHPAD, |
+ XI_TOUCHSCREEN, |
NULL, |
}; |
+enum DeviceType { |
+ DEVICE_TYPE_KEYBOARD, |
+ DEVICE_TYPE_MOUSE, |
+ DEVICE_TYPE_TOUCHPAD, |
+ DEVICE_TYPE_TOUCHSCREEN, |
+ DEVICE_TYPE_OTHER |
+}; |
+ |
typedef base::Callback<void(const std::vector<KeyboardDevice>&)> |
KeyboardDeviceCallback; |
typedef base::Callback<void(const std::vector<TouchscreenDevice>&)> |
TouchscreenDeviceCallback; |
+typedef base::Callback<void(const std::vector<InputDevice>&)> |
+ InputDeviceCallback; |
+ |
// Used for updating the state on the UI thread once device information is |
// parsed on helper threads. |
struct UiCallbacks { |
KeyboardDeviceCallback keyboard_callback; |
TouchscreenDeviceCallback touchscreen_callback; |
+ InputDeviceCallback mouse_callback; |
+ InputDeviceCallback touchpad_callback; |
}; |
// Stores a copy of the XIValuatorClassInfo values so X11 device processing can |
@@ -92,11 +109,13 @@ struct TouchClassInfo { |
}; |
struct DeviceInfo { |
- DeviceInfo(const XIDeviceInfo& device, const base::FilePath& path) |
+ DeviceInfo(const XIDeviceInfo& device, |
+ DeviceType type, |
+ const base::FilePath& path) |
: id(device.deviceid), |
name(device.name), |
use(device.use), |
- enabled(device.enabled), |
+ type(type), |
path(path) { |
for (int i = 0; i < device.num_classes; ++i) { |
switch (device.classes[i]->type) { |
@@ -126,8 +145,8 @@ struct DeviceInfo { |
// Device type (ie: XIMasterPointer) |
int use; |
- // Specifies if the device is enabled and can send events. |
- bool enabled; |
+ // Specifies the type of the device. |
+ DeviceType type; |
// Path to the actual device (ie: /dev/input/eventXX) |
base::FilePath path; |
@@ -147,8 +166,10 @@ struct DisplayState { |
// Returns true if |name| is the name of a known invalid keyboard device. Note, |
// this may return false negatives. |
bool IsKnownInvalidKeyboardDevice(const std::string& name) { |
+ std::string trimmed(name); |
+ base::TrimWhitespaceASCII(name, base::TRIM_TRAILING, &trimmed); |
for (const char* device_name : kKnownInvalidKeyboardDeviceNames) { |
- if (name == device_name) |
+ if (trimmed == device_name) |
return true; |
} |
return false; |
@@ -156,7 +177,7 @@ bool IsKnownInvalidKeyboardDevice(const std::string& name) { |
// Returns true if |name| is the name of a known XTEST device. Note, this may |
// return false negatives. |
-bool IsTestKeyboard(const std::string& name) { |
+bool IsTestDevice(const std::string& name) { |
return name.find("XTEST") != std::string::npos; |
} |
@@ -216,13 +237,11 @@ void HandleKeyboardDevicesInWorker( |
std::vector<KeyboardDevice> devices; |
for (const DeviceInfo& device_info : device_infos) { |
- if (!device_info.enabled || device_info.use != XISlaveKeyboard) |
+ if (device_info.type != DEVICE_TYPE_KEYBOARD) |
+ continue; |
+ if (device_info.use != XISlaveKeyboard) |
continue; // Assume all keyboards are keyboard slaves |
- std::string device_name(device_info.name); |
- base::TrimWhitespaceASCII(device_name, base::TRIM_TRAILING, &device_name); |
- if (IsTestKeyboard(device_name)) |
- continue; // Skip test devices. |
- if (IsKnownInvalidKeyboardDevice(device_name)) |
+ if (IsKnownInvalidKeyboardDevice(device_info.name)) |
continue; // Skip invalid devices. |
InputDeviceType type = GetInputDeviceTypeFromPath(device_info.path); |
devices.push_back(KeyboardDevice(device_info.id, type)); |
@@ -231,6 +250,44 @@ void HandleKeyboardDevicesInWorker( |
reply_runner->PostTask(FROM_HERE, base::Bind(callback, devices)); |
} |
+// Helper used to parse mouse information. When it is done it uses |
+// |reply_runner| and |callback| to update the state on the UI thread. |
+void HandleMouseDevicesInWorker(const std::vector<DeviceInfo>& device_infos, |
+ scoped_refptr<base::TaskRunner> reply_runner, |
+ const InputDeviceCallback& callback) { |
+ std::vector<InputDevice> devices; |
+ for (const DeviceInfo& device_info : device_infos) { |
+ if (device_info.type != DEVICE_TYPE_MOUSE || |
+ device_info.use != XISlavePointer) { |
+ continue; |
+ } |
+ |
+ InputDeviceType type = GetInputDeviceTypeFromPath(device_info.path); |
+ devices.push_back(InputDevice(device_info.id, type)); |
+ } |
+ |
+ reply_runner->PostTask(FROM_HERE, base::Bind(callback, devices)); |
+} |
+ |
+// Helper used to parse touchpad information. When it is done it uses |
+// |reply_runner| and |callback| to update the state on the UI thread. |
+void HandleTouchpadDevicesInWorker(const std::vector<DeviceInfo>& device_infos, |
+ scoped_refptr<base::TaskRunner> reply_runner, |
+ const InputDeviceCallback& callback) { |
+ std::vector<InputDevice> devices; |
+ for (const DeviceInfo& device_info : device_infos) { |
+ if (device_info.type != DEVICE_TYPE_TOUCHPAD || |
+ device_info.use != XISlavePointer) { |
+ continue; |
+ } |
+ |
+ InputDeviceType type = GetInputDeviceTypeFromPath(device_info.path); |
+ devices.push_back(InputDevice(device_info.id, type)); |
+ } |
+ |
+ reply_runner->PostTask(FROM_HERE, base::Bind(callback, devices)); |
+} |
+ |
// Helper used to parse touchscreen information. When it is done it uses |
// |reply_runner| and |callback| to update the state on the UI thread. |
void HandleTouchscreenDevicesInWorker( |
@@ -243,15 +300,19 @@ void HandleTouchscreenDevicesInWorker( |
display_state.mt_position_y == None) |
return; |
- std::set<int> no_match_touchscreen; |
for (const DeviceInfo& device_info : device_infos) { |
- if (!device_info.enabled || (device_info.use != XIFloatingSlave |
- && device_info.use != XISlavePointer)) |
+ if (device_info.type != DEVICE_TYPE_TOUCHSCREEN || |
+ (device_info.use != XIFloatingSlave && |
+ device_info.use != XISlavePointer)) { |
+ continue; |
+ } |
+ |
+ // Touchscreens should be direct touch devices. |
+ if (device_info.touch_class_info.mode != XIDirectTouch) |
continue; |
double max_x = -1.0; |
double max_y = -1.0; |
- bool is_direct_touch = false; |
for (const ValuatorClassInfo& valuator : device_info.valuator_class_infos) { |
if (display_state.mt_position_x == valuator.label) { |
@@ -269,12 +330,8 @@ void HandleTouchscreenDevicesInWorker( |
} |
} |
- if (device_info.touch_class_info.mode) |
- is_direct_touch = device_info.touch_class_info.mode == XIDirectTouch; |
- |
- // Touchscreens should have absolute X and Y axes, and be direct touch |
- // devices. |
- if (max_x > 0.0 && max_y > 0.0 && is_direct_touch) { |
+ // Touchscreens should have absolute X and Y axes. |
+ if (max_x > 0.0 && max_y > 0.0) { |
InputDeviceType type = GetInputDeviceTypeFromPath(device_info.path); |
// |max_x| and |max_y| are inclusive values, so we need to add 1 to get |
// the size. |
@@ -297,6 +354,9 @@ void HandleHotplugEventInWorker( |
devices, display_state, reply_runner, callbacks.touchscreen_callback); |
HandleKeyboardDevicesInWorker( |
devices, reply_runner, callbacks.keyboard_callback); |
+ HandleMouseDevicesInWorker(devices, reply_runner, callbacks.mouse_callback); |
+ HandleTouchpadDevicesInWorker(devices, reply_runner, |
+ callbacks.touchpad_callback); |
} |
DeviceHotplugEventObserver* GetHotplugEventObserver() { |
@@ -311,6 +371,14 @@ void OnTouchscreenDevices(const std::vector<TouchscreenDevice>& devices) { |
GetHotplugEventObserver()->OnTouchscreenDevicesUpdated(devices); |
} |
+void OnMouseDevices(const std::vector<InputDevice>& devices) { |
+ GetHotplugEventObserver()->OnMouseDevicesUpdated(devices); |
+} |
+ |
+void OnTouchpadDevices(const std::vector<InputDevice>& devices) { |
+ GetHotplugEventObserver()->OnTouchpadDevicesUpdated(devices); |
+} |
+ |
} // namespace |
X11HotplugEventHandler::X11HotplugEventHandler() |
@@ -321,14 +389,45 @@ X11HotplugEventHandler::~X11HotplugEventHandler() { |
} |
void X11HotplugEventHandler::OnHotplugEvent() { |
- const XIDeviceList& device_list = |
- DeviceListCacheX11::GetInstance()->GetXI2DeviceList(gfx::GetXDisplay()); |
Display* display = gfx::GetXDisplay(); |
+ const XDeviceList& device_list_xi = |
+ DeviceListCacheX11::GetInstance()->GetXDeviceList(display); |
+ const XIDeviceList& device_list_xi2 = |
+ DeviceListCacheX11::GetInstance()->GetXI2DeviceList(display); |
+ |
+ const int kMaxDeviceNum = 128; |
+ DeviceType device_types[kMaxDeviceNum]; |
+ for (int i = 0; i < kMaxDeviceNum; ++i) |
+ device_types[i] = DEVICE_TYPE_OTHER; |
+ |
+ for (int i = 0; i < device_list_xi.count; ++i) { |
+ int id = device_list_xi[i].id; |
+ if (id < 0 || id >= kMaxDeviceNum) |
+ continue; |
+ |
+ Atom type = device_list_xi[i].type; |
+ if (type == atom_cache_.GetAtom(XI_KEYBOARD)) |
+ device_types[id] = DEVICE_TYPE_KEYBOARD; |
+ else if (type == atom_cache_.GetAtom(XI_MOUSE)) |
+ device_types[id] = DEVICE_TYPE_MOUSE; |
+ else if (type == atom_cache_.GetAtom(XI_TOUCHPAD)) |
+ device_types[id] = DEVICE_TYPE_TOUCHPAD; |
+ else if (type == atom_cache_.GetAtom(XI_TOUCHSCREEN)) |
+ device_types[id] = DEVICE_TYPE_TOUCHSCREEN; |
+ } |
std::vector<DeviceInfo> device_infos; |
- for (int i = 0; i < device_list.count; ++i) { |
- const XIDeviceInfo& device = device_list[i]; |
- device_infos.push_back(DeviceInfo(device, GetDevicePath(display, device))); |
+ for (int i = 0; i < device_list_xi2.count; ++i) { |
+ const XIDeviceInfo& device = device_list_xi2[i]; |
+ if (!device.enabled || IsTestDevice(device.name)) |
+ continue; |
+ |
+ DeviceType device_type = |
+ (device.deviceid >= 0 && device.deviceid < kMaxDeviceNum) |
+ ? device_types[device.deviceid] |
+ : DEVICE_TYPE_OTHER; |
+ device_infos.push_back( |
+ DeviceInfo(device, device_type, GetDevicePath(display, device))); |
} |
// X11 is not thread safe, so first get all the required state. |
@@ -339,8 +438,8 @@ void X11HotplugEventHandler::OnHotplugEvent() { |
UiCallbacks callbacks; |
callbacks.keyboard_callback = base::Bind(&OnKeyboardDevices); |
callbacks.touchscreen_callback = base::Bind(&OnTouchscreenDevices); |
- // TODO(pkotwicz): Compute the lists of mice and touchpads and send the new |
- // lists to DeviceHotplugEventObserver. |
+ callbacks.mouse_callback = base::Bind(&OnMouseDevices); |
+ callbacks.touchpad_callback = base::Bind(&OnTouchpadDevices); |
// Parsing the device information may block, so delegate the operation to a |
// worker thread. Once the device information is extracted the parsed devices |