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

Side by Side Diff: ui/events/x/hotplug_event_handler_x11.cc

Issue 685793002: Move all event related devices from ui/events/ to ui/events/devices/ (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@internal-touchscreens
Patch Set: fix ozone Created 6 years, 1 month 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/x/hotplug_event_handler_x11.h ('k') | ui/events/x/touch_factory_x11.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
(Empty)
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
3 // found in the LICENSE file.
4
5 #include "ui/events/x/hotplug_event_handler_x11.h"
6
7 #include <X11/extensions/XInput.h>
8 #include <X11/extensions/XInput2.h>
9
10 #include <algorithm>
11 #include <cmath>
12 #include <set>
13 #include <string>
14 #include <vector>
15
16 #include "base/command_line.h"
17 #include "base/logging.h"
18 #include "base/process/launch.h"
19 #include "base/strings/string_util.h"
20 #include "base/sys_info.h"
21 #include "ui/events/device_hotplug_event_observer.h"
22 #include "ui/events/device_util_linux.h"
23 #include "ui/events/input_device.h"
24 #include "ui/events/keyboard_device.h"
25 #include "ui/events/touchscreen_device.h"
26 #include "ui/gfx/x/x11_types.h"
27
28 namespace ui {
29
30 namespace {
31
32 // The name of the xinput device corresponding to the AT internal keyboard.
33 const char kATKeyboardName[] = "AT Translated Set 2 keyboard";
34
35 // The prefix of xinput devices corresponding to CrOS EC internal keyboards.
36 const char kCrosEcKeyboardPrefix[] = "cros-ec";
37
38 // Returns true if |name| is the name of a known keyboard device. Note, this may
39 // return false negatives.
40 bool IsKnownKeyboard(const std::string& name) {
41 std::string lower = base::StringToLowerASCII(name);
42 return lower.find("keyboard") != std::string::npos;
43 }
44
45 // Returns true if |name| is the name of a known internal keyboard device. Note,
46 // this may return false negatives.
47 bool IsInternalKeyboard(const std::string& name) {
48 // TODO(rsadam@): Come up with a more generic way of identifying internal
49 // keyboards. See crbug.com/420728.
50 if (name == kATKeyboardName)
51 return true;
52 return name.compare(
53 0u, strlen(kCrosEcKeyboardPrefix), kCrosEcKeyboardPrefix) == 0;
54 }
55
56 // Returns true if |name| is the name of a known XTEST device. Note, this may
57 // return false negatives.
58 bool IsTestKeyboard(const std::string& name) {
59 return name.find("XTEST") != std::string::npos;
60 }
61
62 // We consider the touchscreen to be internal if it is an I2c device.
63 // With the device id, we can query X to get the device's dev input
64 // node eventXXX. Then we search all the dev input nodes registered
65 // by I2C devices to see if we can find eventXXX.
66 bool IsTouchscreenInternal(XDisplay* dpy, int device_id) {
67 #if !defined(CHROMEOS)
68 return false;
69 #else
70 if (!base::SysInfo::IsRunningOnChromeOS())
71 return false;
72 #endif
73
74 // Input device has a property "Device Node" pointing to its dev input node,
75 // e.g. Device Node (250): "/dev/input/event8"
76 Atom device_node = XInternAtom(dpy, "Device Node", False);
77 if (device_node == None)
78 return false;
79
80 Atom actual_type;
81 int actual_format;
82 unsigned long nitems, bytes_after;
83 unsigned char* data;
84 XDevice* dev = XOpenDevice(dpy, device_id);
85 if (!dev)
86 return false;
87
88 if (XGetDeviceProperty(dpy,
89 dev,
90 device_node,
91 0,
92 1000,
93 False,
94 AnyPropertyType,
95 &actual_type,
96 &actual_format,
97 &nitems,
98 &bytes_after,
99 &data) != Success) {
100 XCloseDevice(dpy, dev);
101 return false;
102 }
103 base::FilePath dev_node_path(reinterpret_cast<char*>(data));
104 XFree(data);
105 XCloseDevice(dpy, dev);
106
107 return ui::IsTouchscreenInternal(dev_node_path);
108 }
109
110 } // namespace
111
112 HotplugEventHandlerX11::HotplugEventHandlerX11(
113 DeviceHotplugEventObserver* delegate)
114 : delegate_(delegate) {
115 }
116
117 HotplugEventHandlerX11::~HotplugEventHandlerX11() {
118 }
119
120 void HotplugEventHandlerX11::OnHotplugEvent() {
121 const XIDeviceList& device_list =
122 DeviceListCacheX::GetInstance()->GetXI2DeviceList(gfx::GetXDisplay());
123 HandleTouchscreenDevices(device_list);
124 HandleKeyboardDevices(device_list);
125 }
126
127 void HotplugEventHandlerX11::HandleKeyboardDevices(
128 const XIDeviceList& x11_devices) {
129 std::vector<KeyboardDevice> devices;
130
131 for (int i = 0; i < x11_devices.count; i++) {
132 if (!x11_devices[i].enabled || x11_devices[i].use != XISlaveKeyboard)
133 continue; // Assume all keyboards are keyboard slaves
134 std::string device_name(x11_devices[i].name);
135 base::TrimWhitespaceASCII(device_name, base::TRIM_TRAILING, &device_name);
136 if (IsTestKeyboard(device_name))
137 continue; // Skip test devices.
138 InputDeviceType type;
139 if (IsInternalKeyboard(device_name)) {
140 type = InputDeviceType::INPUT_DEVICE_INTERNAL;
141 } else if (IsKnownKeyboard(device_name)) {
142 type = InputDeviceType::INPUT_DEVICE_EXTERNAL;
143 } else {
144 type = InputDeviceType::INPUT_DEVICE_UNKNOWN;
145 }
146 devices.push_back(
147 KeyboardDevice(x11_devices[i].deviceid, type, device_name));
148 }
149 delegate_->OnKeyboardDevicesUpdated(devices);
150 }
151
152 void HotplugEventHandlerX11::HandleTouchscreenDevices(
153 const XIDeviceList& x11_devices) {
154 std::vector<TouchscreenDevice> devices;
155 Display* display = gfx::GetXDisplay();
156 Atom valuator_x = XInternAtom(display, "Abs MT Position X", False);
157 Atom valuator_y = XInternAtom(display, "Abs MT Position Y", False);
158 if (valuator_x == None || valuator_y == None)
159 return;
160
161 std::set<int> no_match_touchscreen;
162 for (int i = 0; i < x11_devices.count; i++) {
163 if (!x11_devices[i].enabled || x11_devices[i].use != XIFloatingSlave)
164 continue; // Assume all touchscreens are floating slaves
165
166 double max_x = -1.0;
167 double max_y = -1.0;
168 bool is_direct_touch = false;
169
170 for (int j = 0; j < x11_devices[i].num_classes; j++) {
171 XIAnyClassInfo* class_info = x11_devices[i].classes[j];
172
173 if (class_info->type == XIValuatorClass) {
174 XIValuatorClassInfo* valuator_info =
175 reinterpret_cast<XIValuatorClassInfo*>(class_info);
176
177 if (valuator_x == valuator_info->label) {
178 // Ignore X axis valuator with unexpected properties
179 if (valuator_info->number == 0 && valuator_info->mode == Absolute &&
180 valuator_info->min == 0.0) {
181 max_x = valuator_info->max;
182 }
183 } else if (valuator_y == valuator_info->label) {
184 // Ignore Y axis valuator with unexpected properties
185 if (valuator_info->number == 1 && valuator_info->mode == Absolute &&
186 valuator_info->min == 0.0) {
187 max_y = valuator_info->max;
188 }
189 }
190 }
191 #if defined(USE_XI2_MT)
192 if (class_info->type == XITouchClass) {
193 XITouchClassInfo* touch_info =
194 reinterpret_cast<XITouchClassInfo*>(class_info);
195 is_direct_touch = touch_info->mode == XIDirectTouch;
196 }
197 #endif
198 }
199
200 // Touchscreens should have absolute X and Y axes, and be direct touch
201 // devices.
202 if (max_x > 0.0 && max_y > 0.0 && is_direct_touch) {
203 InputDeviceType type =
204 IsTouchscreenInternal(display, x11_devices[i].deviceid)
205 ? InputDeviceType::INPUT_DEVICE_INTERNAL
206 : InputDeviceType::INPUT_DEVICE_EXTERNAL;
207 std::string name(x11_devices[i].name);
208 // |max_x| and |max_y| are inclusive values, so we need to add 1 to get
209 // the size.
210 devices.push_back(TouchscreenDevice(
211 x11_devices[i].deviceid,
212 type,
213 name,
214 gfx::Size(max_x + 1, max_y + 1)));
215 }
216 }
217
218 delegate_->OnTouchscreenDevicesUpdated(devices);
219 }
220
221 } // namespace ui
OLDNEW
« no previous file with comments | « ui/events/x/hotplug_event_handler_x11.h ('k') | ui/events/x/touch_factory_x11.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698