15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Copyright (c) 2012 The Chromium Authors. All rights reserved. 25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be 35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// found in the LICENSE file. 45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 568043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)#include "ui/events/x/touch_factory_x11.h" 65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 75d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include <X11/Xatom.h> 85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <X11/cursorfont.h> 95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <X11/extensions/XInput.h> 105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <X11/extensions/XInput2.h> 115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <X11/extensions/XIproto.h> 125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/basictypes.h" 145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/command_line.h" 155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/compiler_specific.h" 165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/logging.h" 175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/memory/singleton.h" 18ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch#include "base/message_loop/message_loop.h" 197d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)#include "base/strings/string_number_conversions.h" 202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "base/strings/string_split.h" 216e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)#include "base/sys_info.h" 2268043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)#include "ui/events/event_switches.h" 23116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch#include "ui/events/x/device_data_manager_x11.h" 2468043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)#include "ui/events/x/device_list_cache_x.h" 2568043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)#include "ui/gfx/x/x11_types.h" 265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace ui { 285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TouchFactory::TouchFactory() 302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) : pointer_device_lookup_(), 315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) touch_device_available_(false), 322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) touch_events_disabled_(false), 335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) touch_device_list_(), 34f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) max_touch_points_(-1), 351320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci virtual_core_keyboard_device_(-1), 364e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) id_generator_(0) { 37116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch if (!DeviceDataManagerX11::GetInstance()->IsXInput2Available()) 385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4068043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) XDisplay* display = gfx::GetXDisplay(); 415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) UpdateDeviceList(display); 425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) CommandLine* cmdline = CommandLine::ForCurrentProcess(); 442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) touch_events_disabled_ = cmdline->HasSwitch(switches::kTouchEvents) && 452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) cmdline->GetSwitchValueASCII(switches::kTouchEvents) == 462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) switches::kTouchEventsDisabled; 475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TouchFactory::~TouchFactory() { 505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// static 535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TouchFactory* TouchFactory::GetInstance() { 545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return Singleton<TouchFactory>::get(); 555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// static 585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void TouchFactory::SetTouchDeviceListFromCommandLine() { 595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Get a list of pointer-devices that should be treated as touch-devices. 605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // This is primarily used for testing/debugging touch-event processing when a 615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // touch-device isn't available. 625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::string touch_devices = 635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CommandLine::ForCurrentProcess()->GetSwitchValueASCII( 645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) switches::kTouchDevices); 655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!touch_devices.empty()) { 675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::vector<std::string> devs; 685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::vector<unsigned int> device_ids; 695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) unsigned int devid; 705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::SplitString(touch_devices, ',', &devs); 715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (std::vector<std::string>::iterator iter = devs.begin(); 725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) iter != devs.end(); ++iter) { 735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (base::StringToInt(*iter, reinterpret_cast<int*>(&devid))) 745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) device_ids.push_back(devid); 755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) else 765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DLOG(WARNING) << "Invalid touch-device id: " << *iter; 775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ui::TouchFactory::GetInstance()->SetTouchDeviceList(device_ids); 795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void TouchFactory::UpdateDeviceList(Display* display) { 835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Detect touch devices. 845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) touch_device_available_ = false; 855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) touch_device_lookup_.reset(); 865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) touch_device_list_.clear(); 875d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) touchscreen_ids_.clear(); 88f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) max_touch_points_ = -1; 895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if !defined(USE_XI2_MT) 915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // NOTE: The new API for retrieving the list of devices (XIQueryDevice) does 925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // not provide enough information to detect a touch device. As a result, the 935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // old version of query function (XListInputDevices) is used instead. 945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // If XInput2 is not supported, this will return null (with count of -1) so 955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // we assume there cannot be any touch devices. 965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // With XI2.1 or older, we allow only single touch devices. 972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) XDeviceList dev_list = 982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) DeviceListCacheX::GetInstance()->GetXDeviceList(display); 990f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) Atom xi_touchscreen = XInternAtom(display, XI_TOUCHSCREEN, false); 1002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) for (int i = 0; i < dev_list.count; i++) { 1010f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) if (dev_list[i].type == xi_touchscreen) { 1020f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) touch_device_lookup_[dev_list[i].id] = true; 1030f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) touch_device_list_[dev_list[i].id] = false; 1040f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) touch_device_available_ = true; 1055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif 1085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 109116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch if (!DeviceDataManagerX11::GetInstance()->IsXInput2Available()) 110f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) return; 111f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) 1125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Instead of asking X for the list of devices all the time, let's maintain a 1135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // list of pointer devices we care about. 1145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // It should not be necessary to select for slave devices. XInput2 provides 1155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // enough information to the event callback to decide which slave device 1165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // triggered the event, thus decide whether the 'pointer event' is a 1175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // 'mouse event' or a 'touch event'. 1185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // However, on some desktops, some events from a master pointer are 1195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // not delivered to the client. So we select for slave devices instead. 1205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // If the touch device has 'GrabDevice' set and 'SendCoreEvents' unset (which 1215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // is possible), then the device is detected as a floating device, and a 1225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // floating device is not connected to a master device. So it is necessary to 1235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // also select on the floating devices. 1245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) pointer_device_lookup_.reset(); 1252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) XIDeviceList xi_dev_list = 1262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) DeviceListCacheX::GetInstance()->GetXI2DeviceList(display); 1272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) for (int i = 0; i < xi_dev_list.count; i++) { 1282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) XIDeviceInfo* devinfo = xi_dev_list.devices + i; 1295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (devinfo->use == XIFloatingSlave || devinfo->use == XIMasterPointer) { 1305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if defined(USE_XI2_MT) 1315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (int k = 0; k < devinfo->num_classes; ++k) { 1325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) XIAnyClassInfo* xiclassinfo = devinfo->classes[k]; 1335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (xiclassinfo->type == XITouchClass) { 1345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) XITouchClassInfo* tci = 135a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) reinterpret_cast<XITouchClassInfo*>(xiclassinfo); 1365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Only care direct touch device (such as touch screen) right now 1375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (tci->mode == XIDirectTouch) { 1385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) touch_device_lookup_[devinfo->deviceid] = true; 1395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) touch_device_list_[devinfo->deviceid] = true; 1405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) touch_device_available_ = true; 141f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) if (tci->num_touches > 0 && tci->num_touches > max_touch_points_) 142f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) max_touch_points_ = tci->num_touches; 1435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif 1475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) pointer_device_lookup_[devinfo->deviceid] = true; 1481320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci } else if (devinfo->use == XIMasterKeyboard) { 1491320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci virtual_core_keyboard_device_ = devinfo->deviceid; 1505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 151a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) 152a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)#if defined(USE_XI2_MT) 153a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) if (devinfo->use == XIFloatingSlave || devinfo->use == XISlavePointer) { 154a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) for (int k = 0; k < devinfo->num_classes; ++k) { 155a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) XIAnyClassInfo* xiclassinfo = devinfo->classes[k]; 156a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) if (xiclassinfo->type == XITouchClass) { 157a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) XITouchClassInfo* tci = 158a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) reinterpret_cast<XITouchClassInfo*>(xiclassinfo); 159a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) // Only care direct touch device (such as touch screen) right now 160a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) if (tci->mode == XIDirectTouch) 161a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) CacheTouchscreenIds(display, devinfo->deviceid); 162a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) } 163a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) } 164a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) } 165a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)#endif 1665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool TouchFactory::ShouldProcessXI2Event(XEvent* xev) { 1705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK_EQ(GenericEvent, xev->type); 1715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) XIEvent* event = static_cast<XIEvent*>(xev->xcookie.data); 1725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) XIDeviceEvent* xiev = reinterpret_cast<XIDeviceEvent*>(event); 1735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if defined(USE_XI2_MT) 1755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (event->evtype == XI_TouchBegin || 1765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) event->evtype == XI_TouchUpdate || 1775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) event->evtype == XI_TouchEnd) { 1782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return !touch_events_disabled_ && IsTouchDevice(xiev->deviceid); 1795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif 1811320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci // Make sure only key-events from the virtual core keyboard are processed. 1821320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci if (event->evtype == XI_KeyPress || event->evtype == XI_KeyRelease) { 1831320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci return (virtual_core_keyboard_device_ < 0) || 1841320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci (virtual_core_keyboard_device_ == xiev->deviceid); 1851320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci } 186116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch 1875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (event->evtype != XI_ButtonPress && 1885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) event->evtype != XI_ButtonRelease && 1895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) event->evtype != XI_Motion) 1905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return true; 1915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!pointer_device_lookup_[xiev->deviceid]) 1935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 1945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return IsTouchDevice(xiev->deviceid) ? !touch_events_disabled_ : true; 1965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void TouchFactory::SetupXI2ForXWindow(Window window) { 1995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Setup mask for mouse events. It is possible that a device is loaded/plugged 2005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // in after we have setup XInput2 on a window. In such cases, we need to 2015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // either resetup XInput2 for the window, so that we get events from the new 2025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // device, or we need to listen to events from all devices, and then filter 2035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // the events from uninteresting devices. We do the latter because that's 2045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // simpler. 2055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 20668043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) XDisplay* display = gfx::GetXDisplay(); 2075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) unsigned char mask[XIMaskLen(XI_LASTEVENT)]; 2095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) memset(mask, 0, sizeof(mask)); 2105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if defined(USE_XI2_MT) 2125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) XISetMask(mask, XI_TouchBegin); 2135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) XISetMask(mask, XI_TouchUpdate); 2145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) XISetMask(mask, XI_TouchEnd); 2155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif 2165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) XISetMask(mask, XI_ButtonPress); 2175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) XISetMask(mask, XI_ButtonRelease); 2185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) XISetMask(mask, XI_Motion); 2196e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)#if defined(OS_CHROMEOS) 2206e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) if (base::SysInfo::IsRunningOnChromeOS()) { 2216e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) XISetMask(mask, XI_KeyPress); 2226e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) XISetMask(mask, XI_KeyRelease); 2236e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) } 2246e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)#endif 2255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) XIEventMask evmask; 2275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) evmask.deviceid = XIAllDevices; 2285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) evmask.mask_len = sizeof(mask); 2295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) evmask.mask = mask; 2305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) XISelectEvents(display, window, &evmask, 1); 2315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) XFlush(display); 2325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void TouchFactory::SetTouchDeviceList( 2355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const std::vector<unsigned int>& devices) { 2365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) touch_device_lookup_.reset(); 2375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) touch_device_list_.clear(); 2385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (std::vector<unsigned int>::const_iterator iter = devices.begin(); 2395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) iter != devices.end(); ++iter) { 2405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(*iter < touch_device_lookup_.size()); 2415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) touch_device_lookup_[*iter] = true; 2425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) touch_device_list_[*iter] = false; 2435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool TouchFactory::IsTouchDevice(unsigned deviceid) const { 2475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return deviceid < touch_device_lookup_.size() ? 2485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) touch_device_lookup_[deviceid] : false; 2495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool TouchFactory::IsMultiTouchDevice(unsigned int deviceid) const { 2525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return (deviceid < touch_device_lookup_.size() && 2535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) touch_device_lookup_[deviceid]) ? 2545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) touch_device_list_.find(deviceid)->second : 2555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) false; 2565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 258a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)bool TouchFactory::QuerySlotForTrackingID(uint32 tracking_id, int* slot) { 259d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) if (!id_generator_.HasGeneratedIDFor(tracking_id)) 260d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) return false; 261d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) *slot = static_cast<int>(id_generator_.GetGeneratedID(tracking_id)); 262d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) return true; 263a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)} 264a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) 2655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int TouchFactory::GetSlotForTrackingID(uint32 tracking_id) { 266d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) return id_generator_.GetGeneratedID(tracking_id); 2675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2695f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)void TouchFactory::AcquireSlotForTrackingID(uint32 tracking_id) { 2705f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) tracking_id_refcounts_[tracking_id]++; 2715f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)} 2725f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 2735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void TouchFactory::ReleaseSlotForTrackingID(uint32 tracking_id) { 2745f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) tracking_id_refcounts_[tracking_id]--; 2755f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) if (tracking_id_refcounts_[tracking_id] == 0) 2765f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) id_generator_.ReleaseNumber(tracking_id); 2775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool TouchFactory::IsTouchDevicePresent() { 2802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return !touch_events_disabled_ && touch_device_available_; 2815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 283f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)int TouchFactory::GetMaxTouchPoints() const { 284f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) return max_touch_points_; 285f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)} 286f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) 2875f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)void TouchFactory::ResetForTest() { 2885f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) pointer_device_lookup_.reset(); 2895f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) touch_device_lookup_.reset(); 2905f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) touch_device_available_ = false; 2915f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) touch_events_disabled_ = false; 2925f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) touch_device_list_.clear(); 2935f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) touchscreen_ids_.clear(); 2945f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) tracking_id_refcounts_.clear(); 2955f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) max_touch_points_ = -1; 2965f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) id_generator_.ResetForTest(); 2975f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)} 2985f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 299a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)void TouchFactory::SetTouchDeviceForTest( 300a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) const std::vector<unsigned int>& devices) { 301a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) touch_device_lookup_.reset(); 302a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) touch_device_list_.clear(); 303a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) for (std::vector<unsigned int>::const_iterator iter = devices.begin(); 304a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) iter != devices.end(); ++iter) { 305a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) DCHECK(*iter < touch_device_lookup_.size()); 306a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) touch_device_lookup_[*iter] = true; 307a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) touch_device_list_[*iter] = true; 308a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) } 309a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) touch_device_available_ = true; 310a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) touch_events_disabled_ = false; 311a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)} 312a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) 313f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)void TouchFactory::SetPointerDeviceForTest( 314f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) const std::vector<unsigned int>& devices) { 315f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) pointer_device_lookup_.reset(); 316f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) for (std::vector<unsigned int>::const_iterator iter = devices.begin(); 317f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) iter != devices.end(); ++iter) { 318f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) pointer_device_lookup_[*iter] = true; 319f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) } 320f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)} 321f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) 3225d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)void TouchFactory::CacheTouchscreenIds(Display* display, int device_id) { 3235d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) XDevice* device = XOpenDevice(display, device_id); 3245d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (!device) 3255d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) return; 3265d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 3275d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) Atom actual_type_return; 3285d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) int actual_format_return; 3295d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) unsigned long nitems_return; 3305d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) unsigned long bytes_after_return; 3315d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) unsigned char *prop_return; 3325d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 3335d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) const char kDeviceProductIdString[] = "Device Product ID"; 3345d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) Atom device_product_id_atom = 3355d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) XInternAtom(display, kDeviceProductIdString, false); 3365d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 3375d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (device_product_id_atom != None && 3385d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) XGetDeviceProperty(display, device, device_product_id_atom, 0, 2, 3395d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) False, XA_INTEGER, &actual_type_return, 3405d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) &actual_format_return, &nitems_return, 3415d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) &bytes_after_return, &prop_return) == Success) { 3425d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (actual_type_return == XA_INTEGER && 3435d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) actual_format_return == 32 && 3445d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) nitems_return == 2) { 3455d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // An actual_format_return of 32 implies that the returned data is an 3465d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // array of longs. See the description of |prop_return| in `man 3475d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // XGetDeviceProperty` for details. 3485d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) long* ptr = reinterpret_cast<long*>(prop_return); 3495d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 3505d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // Internal displays will have a vid and pid of 0. Ignore them. 3515d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // ptr[0] is the vid, and ptr[1] is the pid. 3525d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (ptr[0] || ptr[1]) 3535d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) touchscreen_ids_.insert(std::make_pair(ptr[0], ptr[1])); 3545d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) } 3555d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) XFree(prop_return); 3565d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) } 3575d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 3585d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) XCloseDevice(display, device); 3595d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)} 3605d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 3615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} // namespace ui 362