OLD | NEW |
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2012 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/devices/x11/touch_factory_x11.h" | 5 #include "ui/events/devices/x11/touch_factory_x11.h" |
6 | 6 |
7 #include <X11/Xatom.h> | 7 #include <X11/Xatom.h> |
8 #include <X11/cursorfont.h> | 8 #include <X11/cursorfont.h> |
9 #include <X11/extensions/XInput.h> | 9 #include <X11/extensions/XInput.h> |
10 #include <X11/extensions/XInput2.h> | 10 #include <X11/extensions/XInput2.h> |
11 #include <X11/extensions/XIproto.h> | 11 #include <X11/extensions/XIproto.h> |
12 | 12 |
13 #include "base/basictypes.h" | 13 #include "base/basictypes.h" |
14 #include "base/command_line.h" | 14 #include "base/command_line.h" |
15 #include "base/compiler_specific.h" | 15 #include "base/compiler_specific.h" |
16 #include "base/logging.h" | 16 #include "base/logging.h" |
17 #include "base/memory/singleton.h" | 17 #include "base/memory/singleton.h" |
18 #include "base/message_loop/message_loop.h" | 18 #include "base/message_loop/message_loop.h" |
19 #include "base/strings/string_number_conversions.h" | 19 #include "base/strings/string_number_conversions.h" |
20 #include "base/strings/string_split.h" | 20 #include "base/strings/string_split.h" |
21 #include "base/sys_info.h" | 21 #include "base/sys_info.h" |
22 #include "ui/events/base_event_utils.h" | 22 #include "ui/events/base_event_utils.h" |
23 #include "ui/events/devices/x11/device_data_manager_x11.h" | 23 #include "ui/events/devices/x11/device_data_manager_x11.h" |
24 #include "ui/events/devices/x11/device_list_cache_x11.h" | 24 #include "ui/events/devices/x11/device_list_cache_x11.h" |
25 #include "ui/events/event_switches.h" | 25 #include "ui/events/event_switches.h" |
26 #include "ui/gfx/x/x11_types.h" | 26 #include "ui/gfx/x/x11_types.h" |
27 | 27 |
28 namespace ui { | 28 namespace ui { |
29 | 29 |
| 30 namespace { |
| 31 |
| 32 bool IsTouchEventsFlagDisabled() { |
| 33 auto* command_line = base::CommandLine::ForCurrentProcess(); |
| 34 bool touch_flag_status = command_line->HasSwitch(switches::kTouchEvents) && |
| 35 command_line->GetSwitchValueASCII(switches::kTouchEvents) == |
| 36 switches::kTouchEventsDisabled; |
| 37 return touch_flag_status; |
| 38 } |
| 39 |
| 40 } // namespace |
| 41 |
| 42 |
30 TouchFactory::TouchFactory() | 43 TouchFactory::TouchFactory() |
31 : pointer_device_lookup_(), | 44 : pointer_device_lookup_(), |
32 touch_device_list_(), | 45 touch_device_list_(), |
33 virtual_core_keyboard_device_(-1), | 46 virtual_core_keyboard_device_(-1), |
34 id_generator_(0) { | 47 id_generator_(0), |
| 48 touch_events_disabled_(IsTouchEventsFlagDisabled()) { |
35 if (!DeviceDataManagerX11::GetInstance()->IsXInput2Available()) | 49 if (!DeviceDataManagerX11::GetInstance()->IsXInput2Available()) |
36 return; | 50 return; |
37 | 51 |
38 XDisplay* display = gfx::GetXDisplay(); | 52 XDisplay* display = gfx::GetXDisplay(); |
39 UpdateDeviceList(display); | 53 UpdateDeviceList(display); |
40 } | 54 } |
41 | 55 |
42 TouchFactory::~TouchFactory() { | 56 TouchFactory::~TouchFactory() { |
43 } | 57 } |
44 | 58 |
(...skipping 91 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
136 } | 150 } |
137 } | 151 } |
138 } | 152 } |
139 } | 153 } |
140 | 154 |
141 bool TouchFactory::ShouldProcessXI2Event(XEvent* xev) { | 155 bool TouchFactory::ShouldProcessXI2Event(XEvent* xev) { |
142 DCHECK_EQ(GenericEvent, xev->type); | 156 DCHECK_EQ(GenericEvent, xev->type); |
143 XIEvent* event = static_cast<XIEvent*>(xev->xcookie.data); | 157 XIEvent* event = static_cast<XIEvent*>(xev->xcookie.data); |
144 XIDeviceEvent* xiev = reinterpret_cast<XIDeviceEvent*>(event); | 158 XIDeviceEvent* xiev = reinterpret_cast<XIDeviceEvent*>(event); |
145 | 159 |
| 160 #if defined(OS_CHROMEOS) |
| 161 const bool is_touch_disabled = touch_events_disabled_ && |
| 162 !GetTouchEventsCrOsX11MasterSwitch(); |
| 163 #else |
| 164 const bool is_touch_disabled = touch_events_disabled_; |
| 165 #endif // defined(OS_CHROMEOS) |
| 166 |
146 if (event->evtype == XI_TouchBegin || | 167 if (event->evtype == XI_TouchBegin || |
147 event->evtype == XI_TouchUpdate || | 168 event->evtype == XI_TouchUpdate || |
148 event->evtype == XI_TouchEnd) { | 169 event->evtype == XI_TouchEnd) { |
149 // Since SetupXI2ForXWindow() selects events from all devices, for a | 170 // Since SetupXI2ForXWindow() selects events from all devices, for a |
150 // touchscreen attached to a master pointer device, X11 sends two | 171 // touchscreen attached to a master pointer device, X11 sends two |
151 // events for each touch: one from the slave (deviceid == the id of | 172 // events for each touch: one from the slave (deviceid == the id of |
152 // the touchscreen device), and one from the master (deviceid == the | 173 // the touchscreen device), and one from the master (deviceid == the |
153 // id of the master pointer device). Instead of processing both | 174 // id of the master pointer device). Instead of processing both |
154 // events, discard the event that comes from the slave, and only | 175 // events, discard the event that comes from the slave, and only |
155 // allow processing the event coming from the master. | 176 // allow processing the event coming from the master. |
156 // For a 'floating' touchscreen device, X11 sends only one event for | 177 // For a 'floating' touchscreen device, X11 sends only one event for |
157 // each touch, with both deviceid and sourceid set to the id of the | 178 // each touch, with both deviceid and sourceid set to the id of the |
158 // touchscreen device. | 179 // touchscreen device. |
159 bool is_from_master_or_float = touch_device_list_[xiev->deviceid]; | 180 bool is_from_master_or_float = touch_device_list_[xiev->deviceid]; |
160 bool is_from_slave_device = !is_from_master_or_float | 181 bool is_from_slave_device = !is_from_master_or_float |
161 && xiev->sourceid == xiev->deviceid; | 182 && xiev->sourceid == xiev->deviceid; |
162 return ui::AreTouchEventsEnabled() && | 183 return !is_touch_disabled && |
163 IsTouchDevice(xiev->deviceid) && | 184 IsTouchDevice(xiev->deviceid) && |
164 !is_from_slave_device; | 185 !is_from_slave_device; |
165 } | 186 } |
166 | 187 |
167 // Make sure only key-events from the virtual core keyboard are processed. | 188 // Make sure only key-events from the virtual core keyboard are processed. |
168 if (event->evtype == XI_KeyPress || event->evtype == XI_KeyRelease) { | 189 if (event->evtype == XI_KeyPress || event->evtype == XI_KeyRelease) { |
169 return (virtual_core_keyboard_device_ < 0) || | 190 return (virtual_core_keyboard_device_ < 0) || |
170 (virtual_core_keyboard_device_ == xiev->deviceid); | 191 (virtual_core_keyboard_device_ == xiev->deviceid); |
171 } | 192 } |
172 | 193 |
173 if (event->evtype != XI_ButtonPress && | 194 if (event->evtype != XI_ButtonPress && |
174 event->evtype != XI_ButtonRelease && | 195 event->evtype != XI_ButtonRelease && |
175 event->evtype != XI_Motion) { | 196 event->evtype != XI_Motion) { |
176 return true; | 197 return true; |
177 } | 198 } |
178 | 199 |
179 if (!pointer_device_lookup_[xiev->deviceid]) | 200 if (!pointer_device_lookup_[xiev->deviceid]) |
180 return false; | 201 return false; |
181 | 202 |
182 return IsTouchDevice(xiev->deviceid) ? ui::AreTouchEventsEnabled() : true; | 203 return IsTouchDevice(xiev->deviceid) ? !is_touch_disabled : true; |
183 } | 204 } |
184 | 205 |
185 void TouchFactory::SetupXI2ForXWindow(Window window) { | 206 void TouchFactory::SetupXI2ForXWindow(Window window) { |
186 // Setup mask for mouse events. It is possible that a device is loaded/plugged | 207 // Setup mask for mouse events. It is possible that a device is loaded/plugged |
187 // in after we have setup XInput2 on a window. In such cases, we need to | 208 // in after we have setup XInput2 on a window. In such cases, we need to |
188 // either resetup XInput2 for the window, so that we get events from the new | 209 // either resetup XInput2 for the window, so that we get events from the new |
189 // device, or we need to listen to events from all devices, and then filter | 210 // device, or we need to listen to events from all devices, and then filter |
190 // the events from uninteresting devices. We do the latter because that's | 211 // the events from uninteresting devices. We do the latter because that's |
191 // simpler. | 212 // simpler. |
192 | 213 |
(...skipping 66 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
259 | 280 |
260 int TouchFactory::GetSlotForTrackingID(uint32 tracking_id) { | 281 int TouchFactory::GetSlotForTrackingID(uint32 tracking_id) { |
261 return id_generator_.GetGeneratedID(tracking_id); | 282 return id_generator_.GetGeneratedID(tracking_id); |
262 } | 283 } |
263 | 284 |
264 void TouchFactory::ReleaseSlotForTrackingID(uint32 tracking_id) { | 285 void TouchFactory::ReleaseSlotForTrackingID(uint32 tracking_id) { |
265 id_generator_.ReleaseNumber(tracking_id); | 286 id_generator_.ReleaseNumber(tracking_id); |
266 } | 287 } |
267 | 288 |
268 bool TouchFactory::IsTouchDevicePresent() { | 289 bool TouchFactory::IsTouchDevicePresent() { |
269 return ui::AreTouchEventsEnabled() && touch_device_lookup_.any(); | 290 #if defined(OS_CHROMEOS) |
| 291 const bool is_touch_disabled = touch_events_disabled_ && |
| 292 !GetTouchEventsCrOsX11MasterSwitch(); |
| 293 #else |
| 294 const bool is_touch_disabled = touch_events_disabled_; |
| 295 #endif // defined(OS_CHROMEOS) |
| 296 |
| 297 return !is_touch_disabled && touch_device_lookup_.any(); |
270 } | 298 } |
271 | 299 |
272 void TouchFactory::ResetForTest() { | 300 void TouchFactory::ResetForTest() { |
273 pointer_device_lookup_.reset(); | 301 pointer_device_lookup_.reset(); |
274 touch_device_lookup_.reset(); | 302 touch_device_lookup_.reset(); |
275 touch_device_list_.clear(); | 303 touch_device_list_.clear(); |
276 touchscreen_ids_.clear(); | 304 touchscreen_ids_.clear(); |
277 id_generator_.ResetForTest(); | 305 id_generator_.ResetForTest(); |
| 306 touch_events_disabled_ = false; |
| 307 |
| 308 #if defined(OS_CHROMEOS) |
| 309 SetTouchEventsCrOsX11MasterSwitch(true); |
| 310 #endif // defined(OS_CHROMEOS) |
278 } | 311 } |
279 | 312 |
280 void TouchFactory::SetTouchDeviceForTest( | 313 void TouchFactory::SetTouchDeviceForTest( |
281 const std::vector<int>& devices) { | 314 const std::vector<int>& devices) { |
282 touch_device_lookup_.reset(); | 315 touch_device_lookup_.reset(); |
283 touch_device_list_.clear(); | 316 touch_device_list_.clear(); |
284 for (std::vector<int>::const_iterator iter = devices.begin(); | 317 for (std::vector<int>::const_iterator iter = devices.begin(); |
285 iter != devices.end(); ++iter) { | 318 iter != devices.end(); ++iter) { |
286 DCHECK(IsValidDevice(*iter)); | 319 DCHECK(IsValidDevice(*iter)); |
287 touch_device_lookup_[*iter] = true; | 320 touch_device_lookup_[*iter] = true; |
288 touch_device_list_[*iter] = true; | 321 touch_device_list_[*iter] = true; |
289 } | 322 } |
| 323 touch_events_disabled_ = false; |
| 324 |
| 325 #if defined(OS_CHROMEOS) |
| 326 SetTouchEventsCrOsX11MasterSwitch(true); |
| 327 #endif // defined(OS_CHROMEOS) |
290 } | 328 } |
291 | 329 |
292 void TouchFactory::SetPointerDeviceForTest( | 330 void TouchFactory::SetPointerDeviceForTest( |
293 const std::vector<int>& devices) { | 331 const std::vector<int>& devices) { |
294 pointer_device_lookup_.reset(); | 332 pointer_device_lookup_.reset(); |
295 for (std::vector<int>::const_iterator iter = devices.begin(); | 333 for (std::vector<int>::const_iterator iter = devices.begin(); |
296 iter != devices.end(); ++iter) { | 334 iter != devices.end(); ++iter) { |
297 pointer_device_lookup_[*iter] = true; | 335 pointer_device_lookup_[*iter] = true; |
298 } | 336 } |
299 } | 337 } |
300 | 338 |
301 void TouchFactory::CacheTouchscreenIds(int device_id) { | 339 void TouchFactory::CacheTouchscreenIds(int device_id) { |
302 if (!DeviceDataManager::HasInstance()) | 340 if (!DeviceDataManager::HasInstance()) |
303 return; | 341 return; |
304 std::vector<TouchscreenDevice> touchscreens = | 342 std::vector<TouchscreenDevice> touchscreens = |
305 DeviceDataManager::GetInstance()->touchscreen_devices(); | 343 DeviceDataManager::GetInstance()->touchscreen_devices(); |
306 const auto it = | 344 const auto it = |
307 std::find_if(touchscreens.begin(), touchscreens.end(), | 345 std::find_if(touchscreens.begin(), touchscreens.end(), |
308 [device_id](const TouchscreenDevice& touchscreen) { | 346 [device_id](const TouchscreenDevice& touchscreen) { |
309 return touchscreen.id == device_id; | 347 return touchscreen.id == device_id; |
310 }); | 348 }); |
311 // Internal displays will have a vid and pid of 0. Ignore them. | 349 // Internal displays will have a vid and pid of 0. Ignore them. |
312 if (it != touchscreens.end() && it->vendor_id && it->product_id) | 350 if (it != touchscreens.end() && it->vendor_id && it->product_id) |
313 touchscreen_ids_.insert(std::make_pair(it->vendor_id, it->product_id)); | 351 touchscreen_ids_.insert(std::make_pair(it->vendor_id, it->product_id)); |
314 } | 352 } |
315 | 353 |
316 } // namespace ui | 354 } // namespace ui |
OLD | NEW |