diff options
author | sadrul@chromium.org <sadrul@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2012-05-25 16:09:26 +0000 |
---|---|---|
committer | sadrul@chromium.org <sadrul@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2012-05-25 16:09:26 +0000 |
commit | 4ba96d0e34ef8c2836045161b342516e88bcb891 (patch) | |
tree | 6495bb9c466250e927489b62ef41551c89539228 /ui | |
parent | a9e2990775165b2780a187a5a42917a967dcb69c (diff) | |
download | chromium_src-4ba96d0e34ef8c2836045161b342516e88bcb891.zip chromium_src-4ba96d0e34ef8c2836045161b342516e88bcb891.tar.gz chromium_src-4ba96d0e34ef8c2836045161b342516e88bcb891.tar.bz2 |
XI2.2: Make sure valuators values are reported correctly.
With MT-B/XI2.2, valuators in an XEvent are not reported if the values haven't
changed from the previous event. So it is necessary to remember these valuators
so that chrome doesn't think X/device doesn't know about the valuators.
BUG=129395
TEST=manually
Review URL: https://chromiumcodereview.appspot.com/10412060
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@139051 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'ui')
-rw-r--r-- | ui/base/touch/touch_factory.cc | 149 | ||||
-rw-r--r-- | ui/base/touch/touch_factory.h | 67 | ||||
-rw-r--r-- | ui/base/x/events_x.cc | 45 | ||||
-rw-r--r-- | ui/base/x/valuators.cc | 182 | ||||
-rw-r--r-- | ui/base/x/valuators.h | 113 | ||||
-rw-r--r-- | ui/ui.gyp | 2 |
6 files changed, 323 insertions, 235 deletions
diff --git a/ui/base/touch/touch_factory.cc b/ui/base/touch/touch_factory.cc index b3c254c..4eeba93 100644 --- a/ui/base/touch/touch_factory.cc +++ b/ui/base/touch/touch_factory.cc @@ -22,59 +22,6 @@ namespace { // The X cursor is hidden if it is idle for kCursorIdleSeconds seconds. int kCursorIdleSeconds = 5; -// Given the TouchParam, return the correspoding XIValuatorClassInfo using -// the X device information through Atom name matching. -XIValuatorClassInfo* FindTPValuator(Display* display, - XIDeviceInfo* info, - ui::TouchFactory::TouchParam tp) { - // Lookup table for mapping TouchParam to Atom string used in X. - // A full set of Atom strings can be found at xserver-properties.h. - static struct { - ui::TouchFactory::TouchParam tp; - const char* atom; - } kTouchParamAtom[] = { - { ui::TouchFactory::TP_TOUCH_MAJOR, "Abs MT Touch Major" }, - { ui::TouchFactory::TP_TOUCH_MINOR, "Abs MT Touch Minor" }, - { ui::TouchFactory::TP_ORIENTATION, "Abs MT Orientation" }, - { ui::TouchFactory::TP_PRESSURE, "Abs MT Pressure" }, -#if !defined(USE_XI2_MT) - // For Slot ID, See this chromeos revision: http://git.chromium.org/gitweb/? - // p=chromiumos/overlays/chromiumos-overlay.git; - // a=commit;h=9164d0a75e48c4867e4ef4ab51f743ae231c059a - { ui::TouchFactory::TP_SLOT_ID, "Abs MT Slot ID" }, -#endif - { ui::TouchFactory::TP_TRACKING_ID, "Abs MT Tracking ID" }, - { ui::TouchFactory::TP_LAST_ENTRY, NULL }, - }; - - const char* atom_tp = NULL; - - for (size_t i = 0; i < ARRAYSIZE_UNSAFE(kTouchParamAtom); i++) { - if (tp == kTouchParamAtom[i].tp) { - atom_tp = kTouchParamAtom[i].atom; - break; - } - } - - if (!atom_tp) - return NULL; - - for (int i = 0; i < info->num_classes; i++) { - if (info->classes[i]->type != XIValuatorClass) - continue; - XIValuatorClassInfo* v = - reinterpret_cast<XIValuatorClassInfo*>(info->classes[i]); - - if (v->label) { - ui::XScopedString atom(XGetAtomName(display, v->label)); - if (atom.string() && strcmp(atom.string(), atom_tp) == 0) - return v; - } - } - - return NULL; -} - } // namespace namespace ui { @@ -211,8 +158,6 @@ void TouchFactory::UpdateDeviceList(Display* display) { } if (devices) XIFreeDeviceInfo(devices); - - SetupValuator(); } bool TouchFactory::ShouldProcessXI2Event(XEvent* xev) { @@ -278,8 +223,6 @@ void TouchFactory::SetTouchDeviceList( touch_device_lookup_[*iter] = true; touch_device_list_[*iter] = false; } - - SetupValuator(); } bool TouchFactory::IsTouchDevice(unsigned deviceid) const { @@ -427,100 +370,8 @@ void TouchFactory::SetCursorVisible(bool show, bool start_timer) { XDefineCursor(display, window, invisible_cursor_); } -bool TouchFactory::ExtractTouchParam(const XEvent& xev, - TouchParam tp, - float* value) { - XIDeviceEvent* xiev = static_cast<XIDeviceEvent*>(xev.xcookie.data); - if (xiev->sourceid >= kMaxDeviceNum) - return false; - int v = valuator_lookup_[xiev->sourceid][tp]; - if (v >= 0 && XIMaskIsSet(xiev->valuators.mask, v)) { - *value = xiev->valuators.values[v]; - return true; - } - -#if defined(USE_XI2_MT) - // With XInput2 MT, Tracking ID is provided in the detail field. - if (tp == TP_TRACKING_ID) { - *value = xiev->detail; - return true; - } -#endif - - return false; -} - -bool TouchFactory::NormalizeTouchParam(unsigned int deviceid, - TouchParam tp, - float* value) { - float max_value; - float min_value; - if (GetTouchParamRange(deviceid, tp, &min_value, &max_value)) { - *value = (*value - min_value) / (max_value - min_value); - DCHECK(*value >= 0.0 && *value <= 1.0); - return true; - } - return false; -} - -bool TouchFactory::GetTouchParamRange(unsigned int deviceid, - TouchParam tp, - float* min, - float* max) { - if (valuator_lookup_[deviceid][tp] >= 0) { - *min = touch_param_min_[deviceid][tp]; - *max = touch_param_max_[deviceid][tp]; - return true; - } - return false; -} - bool TouchFactory::IsTouchDevicePresent() { return (touch_device_available_ && touch_events_allowed_); } -void TouchFactory::SetupValuator() { - memset(valuator_lookup_, -1, sizeof(valuator_lookup_)); - memset(touch_param_min_, 0, sizeof(touch_param_min_)); - memset(touch_param_max_, 0, sizeof(touch_param_max_)); - - Display* display = ui::GetXDisplay(); - int ndevice; - XIDeviceInfo* info_list = XIQueryDevice(display, XIAllDevices, &ndevice); - - for (int i = 0; i < ndevice; i++) { - XIDeviceInfo* info = info_list + i; - - if (!IsTouchDevice(info->deviceid)) - continue; - - for (int j = 0; j < TP_LAST_ENTRY; j++) { - TouchParam tp = static_cast<TouchParam>(j); - XIValuatorClassInfo* valuator = FindTPValuator(display, info, tp); - if (valuator) { - valuator_lookup_[info->deviceid][j] = valuator->number; - touch_param_min_[info->deviceid][j] = valuator->min; - touch_param_max_[info->deviceid][j] = valuator->max; - } - } - -#if !defined(USE_XI2_MT) - // In order to support multi-touch with XI2.0, we need both a slot_id and - // tracking_id valuator. Without these we'll treat the device as a - // single-touch device (like a mouse). - // TODO(rbyers): Multi-touch is disabled: http://crbug.com/112329 - //if (valuator_lookup_[info->deviceid][TP_SLOT_ID] == -1 || - // valuator_lookup_[info->deviceid][TP_TRACKING_ID] == -1) { - DVLOG(1) << "Touch device " << info->deviceid << - " does not provide enough information for multi-touch, treating as " - "a single-touch device."; - touch_device_list_[info->deviceid] = false; - //} -#endif - } - - if (info_list) - XIFreeDeviceInfo(info_list); -} - } // namespace ui diff --git a/ui/base/touch/touch_factory.h b/ui/base/touch/touch_factory.h index 407cca3..feef80a 100644 --- a/ui/base/touch/touch_factory.h +++ b/ui/base/touch/touch_factory.h @@ -29,39 +29,6 @@ class UI_EXPORT TouchFactory { ~TouchFactory(); public: - // Define the touch params following the Multi-touch Protocol. - enum TouchParam { - TP_TOUCH_MAJOR = 0, // Length of the touch area. - TP_TOUCH_MINOR, // Width of the touch area. - TP_ORIENTATION, // Angle between the X-axis and the major axis of the - // touch area. - TP_PRESSURE, // Pressure of the touch contact. - - // NOTE: A touch event can have multiple touch points. So when we receive a - // touch event, we need to determine which point triggered the event. - // A touch point can have both a 'Slot ID' and a 'Tracking ID', and they can - // be (in fact, usually are) different. The 'Slot ID' ranges between 0 and - // (X - 1), where X is the maximum touch points supported by the device. The - // 'Tracking ID' can be any 16-bit value. With XInput 2.0, an XI_Motion - // event that comes from a currently-unused 'Slot ID' indicates the creation - // of a new touch point, and any event that comes with a 0 value for - // 'Tracking ID' marks the removal of a touch point. During the lifetime of - // a touchpoint, we use the 'Slot ID' as its identifier. The XI_ButtonPress - // and XI_ButtonRelease events are ignored. -#if !defined(USE_XI2_MT) - TP_SLOT_ID, // ID of the finger that triggered a touch event - // (useful when tracking multiple simultaneous - // touches) -#endif - // NOTE for XInput MT: 'Tracking ID' is provided in every touch event to - // track individual touch. 'Tracking ID' is an unsigned 32-bit value and - // is increased for each new touch. It will wrap back to 0 when reaching - // the numerical limit. - TP_TRACKING_ID, // ID of the touch point. - - TP_LAST_ENTRY - }; - // Returns the TouchFactory singleton. static TouchFactory* GetInstance(); @@ -120,24 +87,6 @@ class UI_EXPORT TouchFactory { return is_cursor_visible_; } - // Extract the TouchParam from the XEvent. Return true and the value is set - // if the TouchParam is found, false and value unchanged if the TouchParam - // is not found. - bool ExtractTouchParam(const XEvent& xev, TouchParam tp, float* value); - - // Normalize the TouchParam with value on deviceid to fall into [0, 1]. - // *value = (*value - min_value_of_tp) / (max_value_of_tp - min_value_of_tp) - // Returns true and sets the normalized value in|value| if normalization is - // successful. Returns false and |value| is unchanged otherwise. - bool NormalizeTouchParam(unsigned int deviceid, TouchParam tp, float* value); - - // Extract the range of the TouchParam. Return true if the range is available - // and written into min & max, false if the range is not available. - bool GetTouchParamRange(unsigned int deviceid, - TouchParam tp, - float* min, - float* max); - // Whether any touch device is currently present and enabled. bool IsTouchDevicePresent(); @@ -146,10 +95,6 @@ class UI_EXPORT TouchFactory { SetCursorVisible(false, false); } - // Setup the internal bookkeeping of the touch params valuator information for - // touch devices - void SetupValuator(); - // Requirement for Signleton friend struct DefaultSingletonTraits<TouchFactory>; @@ -198,18 +143,6 @@ class UI_EXPORT TouchFactory { // capable. std::map<int, bool> touch_device_list_; - // Index table to find the valuator for the TouchParam on the specific device - // by valuator_lookup_[device_id][touch_params]. Use 2-D array to get fast - // index at the expense of space. If the kMaxDeviceNum grows larger that the - // space waste becomes a concern, the 2D lookup table can be replaced by a - // hash map. - signed char valuator_lookup_[kMaxDeviceNum][TP_LAST_ENTRY]; - - // Index table to find the min & max value of the TouchParam on a specific - // device. - int touch_param_min_[kMaxDeviceNum][TP_LAST_ENTRY]; - int touch_param_max_[kMaxDeviceNum][TP_LAST_ENTRY]; - // Maximum simultaneous touch points. static const int kMaxTouchPoints = 32; diff --git a/ui/base/x/events_x.cc b/ui/base/x/events_x.cc index f166a86..ce97b81 100644 --- a/ui/base/x/events_x.cc +++ b/ui/base/x/events_x.cc @@ -15,6 +15,7 @@ #include "ui/base/keycodes/keyboard_code_conversion_x.h" #include "ui/base/ui_base_switches.h" #include "ui/base/touch/touch_factory.h" +#include "ui/base/x/valuators.h" #include "ui/base/x/x11_util.h" #include "ui/gfx/point.h" #include "ui/gfx/monitor.h" @@ -49,7 +50,7 @@ const int kMinWheelButton = 4; const int kMaxWheelButton = 7; // A class to support the detection of scroll events, using X11 valuators. -class UI_EXPORT CMTEventData { +class CMTEventData { public: // Returns the ScrollEventData singleton. static CMTEventData* GetInstance() { @@ -373,7 +374,7 @@ class UI_EXPORT CMTEventData { // A class to track current modifier state on master device. Only track ctrl, // alt, shift and caps lock keys currently. The tracked state can then be used // by floating device. -class UI_EXPORT XModifierStateWatcher{ +class XModifierStateWatcher{ public: static XModifierStateWatcher* GetInstance() { return Singleton<XModifierStateWatcher>::get(); @@ -526,9 +527,11 @@ ui::EventType GetTouchEventType(const base::NativeEvent& native_event) { // when necessary, by a RWHVV. // TODO(sad): When should _CANCELLED be generated? + ui::ValuatorTracker* valuators = ui::ValuatorTracker::GetInstance(); + float slot; - if (!factory->ExtractTouchParam(*native_event, ui::TouchFactory::TP_SLOT_ID, - &slot)) + if (!valuators->ExtractValuator( + *native_event, ui::ValuatorTracker::VAL_SLOT_ID, &slot)) return ui::ET_UNKNOWN; if (!factory->IsSlotUsed(slot)) { @@ -537,8 +540,8 @@ ui::EventType GetTouchEventType(const base::NativeEvent& native_event) { } float tracking; - if (!factory->ExtractTouchParam(*native_event, - ui::TouchFactory::TP_TRACKING_ID, &tracking)) + if (!valuators->ExtractValuator( + *native_event, ui::ValuatorTracker::VAL_TRACKING_ID, &tracking)) return ui::ET_UNKNOWN; if (tracking == 0l) { @@ -551,9 +554,10 @@ ui::EventType GetTouchEventType(const base::NativeEvent& native_event) { } float GetTouchParamFromXEvent(XEvent* xev, - ui::TouchFactory::TouchParam tp, + ui::ValuatorTracker::Valuator val, float default_value) { - ui::TouchFactory::GetInstance()->ExtractTouchParam(*xev, tp, &default_value); + ui::ValuatorTracker::GetInstance()->ExtractValuator( + *xev, val, &default_value); return default_value; } @@ -626,6 +630,7 @@ void UpdateDeviceList() { Display* display = GetXDisplay(); CMTEventData::GetInstance()->UpdateDeviceList(display); TouchFactory::GetInstance()->UpdateDeviceList(display); + ValuatorTracker::GetInstance()->SetupValuator(); } EventType EventTypeFromNative(const base::NativeEvent& native_event) { @@ -874,10 +879,12 @@ int GetTouchId(const base::NativeEvent& xev) { return slot; } + ui::ValuatorTracker* valuators = ui::ValuatorTracker::GetInstance(); + #if defined(USE_XI2_MT) float tracking_id; - if (!factory->ExtractTouchParam( - *xev, ui::TouchFactory::TP_TRACKING_ID, &tracking_id)) { + if (!valuators->ExtractValuator( + *xev, ui::ValuatorTracker::VAL_TRACKING_ID, &tracking_id)) { LOG(ERROR) << "Could not get the slot ID for the event. Using 0."; } else { slot = factory->GetSlotForTrackingID(tracking_id); @@ -888,8 +895,8 @@ int GetTouchId(const base::NativeEvent& xev) { } } #else - if (!factory->ExtractTouchParam( - *xev, ui::TouchFactory::TP_SLOT_ID, &slot)) + if (!valuators->ExtractValuator( + *xev, ui::ValuatorTracker::VAL_SLOT_ID, &slot)) LOG(ERROR) << "Could not get the slot ID for the event. Using 0."; #endif return slot; @@ -897,28 +904,28 @@ int GetTouchId(const base::NativeEvent& xev) { float GetTouchRadiusX(const base::NativeEvent& native_event) { return GetTouchParamFromXEvent(native_event, - ui::TouchFactory::TP_TOUCH_MAJOR, 0.0) / 2.0; + ui::ValuatorTracker::VAL_TOUCH_MAJOR, 0.0) / 2.0; } float GetTouchRadiusY(const base::NativeEvent& native_event) { return GetTouchParamFromXEvent(native_event, - ui::TouchFactory::TP_TOUCH_MINOR, 0.0) / 2.0; + ui::ValuatorTracker::VAL_TOUCH_MINOR, 0.0) / 2.0; } float GetTouchAngle(const base::NativeEvent& native_event) { return GetTouchParamFromXEvent(native_event, - ui::TouchFactory::TP_ORIENTATION, 0.0) / 2.0; + ui::ValuatorTracker::VAL_ORIENTATION, 0.0) / 2.0; } float GetTouchForce(const base::NativeEvent& native_event) { float force = 0.0; - force = GetTouchParamFromXEvent(native_event, ui::TouchFactory::TP_PRESSURE, - 0.0); + force = GetTouchParamFromXEvent(native_event, + ui::ValuatorTracker::VAL_PRESSURE, 0.0); unsigned int deviceid = static_cast<XIDeviceEvent*>(native_event->xcookie.data)->sourceid; // Force is normalized to fall into [0, 1] - if (!ui::TouchFactory::GetInstance()->NormalizeTouchParam( - deviceid, ui::TouchFactory::TP_PRESSURE, &force)) + if (!ui::ValuatorTracker::GetInstance()->NormalizeValuator( + deviceid, ui::ValuatorTracker::VAL_PRESSURE, &force)) force = 0.0; return force; } diff --git a/ui/base/x/valuators.cc b/ui/base/x/valuators.cc new file mode 100644 index 0000000..6df343b --- /dev/null +++ b/ui/base/x/valuators.cc @@ -0,0 +1,182 @@ +// Copyright (c) 2012 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "ui/base/x/valuators.h" + +#include <X11/extensions/XInput2.h> + +#include "ui/base/x/x11_util.h" +#include "ui/base/touch/touch_factory.h" + +namespace { + +#define AXIS_LABEL_ABS_MT_TOUCH_MAJOR "Abs MT Touch Major" +#define AXIS_LABEL_ABS_MT_TOUCH_MINOR "Abs MT Touch Minor" +#define AXIS_LABEL_ABS_MT_ORIENTATION "Abs MT Orientation" +#define AXIS_LABEL_ABS_MT_PRESSURE "Abs MT Pressure" +#define AXIS_LABEL_ABS_MT_SLOT_ID "Abs MT Slot ID" +#define AXIS_LABEL_ABS_MT_TRACKING_ID "Abs MT Tracking ID" + +// Given the Valuator, return the correspoding XIValuatorClassInfo using +// the X device information through Atom name matching. +XIValuatorClassInfo* FindValuator(Display* display, + XIDeviceInfo* info, + ui::ValuatorTracker::Valuator val) { + // Lookup table for mapping Valuator to Atom string used in X. + // A full set of Atom strings can be found at xserver-properties.h. + static struct { + ui::ValuatorTracker::Valuator val; + Atom atom; + } kValuatorAtom[] = { + { ui::ValuatorTracker::VAL_TOUCH_MAJOR, + XInternAtom(ui::GetXDisplay(), AXIS_LABEL_ABS_MT_TOUCH_MAJOR, false) }, + { ui::ValuatorTracker::VAL_TOUCH_MINOR, + XInternAtom(ui::GetXDisplay(), AXIS_LABEL_ABS_MT_TOUCH_MINOR, false) }, + { ui::ValuatorTracker::VAL_ORIENTATION, + XInternAtom(ui::GetXDisplay(), AXIS_LABEL_ABS_MT_ORIENTATION, false) }, + { ui::ValuatorTracker::VAL_PRESSURE, + XInternAtom(ui::GetXDisplay(), AXIS_LABEL_ABS_MT_PRESSURE, false) }, +#if !defined(USE_XI2_MT) + // For Slot ID, See this chromeos revision: http://git.chromium.org/gitweb/? + // p=chromiumos/overlays/chromiumos-overlay.git; + // a=commit;h=9164d0a75e48c4867e4ef4ab51f743ae231c059a + { ui::ValuatorTracker::VAL_SLOT_ID, + XInternAtom(ui::GetXDisplay(), AXIS_LABEL_ABS_MT_SLOT_ID, false) }, +#endif + { ui::ValuatorTracker::VAL_TRACKING_ID, + XInternAtom(ui::GetXDisplay(), AXIS_LABEL_ABS_MT_TRACKING_ID, false) }, + { ui::ValuatorTracker::VAL_LAST_ENTRY, None }, + }; + + Atom atom = None; + + for (size_t i = 0; i < ARRAYSIZE_UNSAFE(kValuatorAtom); i++) { + if (val == kValuatorAtom[i].val) { + atom = kValuatorAtom[i].atom; + break; + } + } + + if (atom == None) + return NULL; + + for (int i = 0; i < info->num_classes; i++) { + if (info->classes[i]->type != XIValuatorClass) + continue; + XIValuatorClassInfo* v = + reinterpret_cast<XIValuatorClassInfo*>(info->classes[i]); + if (v->label && atom == v->label) + return v; + } + + return NULL; +} + +} // namespace + +namespace ui { + +ValuatorTracker::ValuatorTracker() { + SetupValuator(); +} + +ValuatorTracker::~ValuatorTracker() { +} + +// static +ValuatorTracker* ValuatorTracker::GetInstance() { + return Singleton<ValuatorTracker>::get(); +} + +bool ValuatorTracker::ExtractValuator(const XEvent& xev, + Valuator val, + float* value) { + XIDeviceEvent* xiev = static_cast<XIDeviceEvent*>(xev.xcookie.data); + if (xiev->sourceid >= kMaxDeviceNum || xiev->deviceid >= kMaxDeviceNum) + return false; + int val_index = valuator_lookup_[xiev->sourceid][val]; + if (val_index >= 0) { + if (XIMaskIsSet(xiev->valuators.mask, val_index)) { + double* valuators = xiev->valuators.values; + while (val_index--) { + if (XIMaskIsSet(xiev->valuators.mask, val_index)) + ++valuators; + } + *value = *valuators; + last_seen_valuator_[xiev->deviceid][val] = *value; + return true; + } else { + *value = last_seen_valuator_[xiev->deviceid][val]; + } + } + +#if defined(USE_XI2_MT) + // With XInput2 MT, Tracking ID is provided in the detail field. + if (val == VAL_TRACKING_ID) { + *value = xiev->detail; + return true; + } +#endif + + return false; +} + +bool ValuatorTracker::NormalizeValuator(unsigned int deviceid, + Valuator val, + float* value) { + float max_value; + float min_value; + if (GetValuatorRange(deviceid, val, &min_value, &max_value)) { + *value = (*value - min_value) / (max_value - min_value); + DCHECK(*value >= 0.0 && *value <= 1.0); + return true; + } + return false; +} + +bool ValuatorTracker::GetValuatorRange(unsigned int deviceid, + Valuator val, + float* min, + float* max) { + if (valuator_lookup_[deviceid][val] >= 0) { + *min = valuator_min_[deviceid][val]; + *max = valuator_max_[deviceid][val]; + return true; + } + return false; +} + +void ValuatorTracker::SetupValuator() { + memset(valuator_lookup_, -1, sizeof(valuator_lookup_)); + memset(valuator_min_, 0, sizeof(valuator_min_)); + memset(valuator_max_, 0, sizeof(valuator_max_)); + memset(last_seen_valuator_, 0, sizeof(last_seen_valuator_)); + + Display* display = GetXDisplay(); + int ndevice; + XIDeviceInfo* info_list = XIQueryDevice(display, XIAllDevices, &ndevice); + TouchFactory* factory = TouchFactory::GetInstance(); + + for (int i = 0; i < ndevice; i++) { + XIDeviceInfo* info = info_list + i; + + if (!factory->IsTouchDevice(info->deviceid)) + continue; + + for (int j = 0; j < VAL_LAST_ENTRY; j++) { + Valuator val = static_cast<Valuator>(j); + XIValuatorClassInfo* valuator = FindValuator(display, info, val); + if (valuator) { + valuator_lookup_[info->deviceid][j] = valuator->number; + valuator_min_[info->deviceid][j] = valuator->min; + valuator_max_[info->deviceid][j] = valuator->max; + } + } + } + + if (info_list) + XIFreeDeviceInfo(info_list); +} + +} // namespace ui diff --git a/ui/base/x/valuators.h b/ui/base/x/valuators.h new file mode 100644 index 0000000..5cef206 --- /dev/null +++ b/ui/base/x/valuators.h @@ -0,0 +1,113 @@ +// Copyright (c) 2012 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef UI_BASE_X_VALUATORS_H_ +#define UI_BASE_X_VALUATORS_H_ + +#include <map> + +#include "base/memory/singleton.h" + +typedef union _XEvent XEvent; + +namespace ui { + +// A valuator is not reported in an XEvent if it hasn't changed from the +// previous event from the same device. As a result, it is necessary to track +// the last reported valuator values for a specific device. +// Right now, this is only used to keep track of valuators for events coming in +// from touch-devices, but it can be used for other devices as well. +class ValuatorTracker { + private: + ValuatorTracker(); + ~ValuatorTracker(); + + public: + // Define the valuators following the Multi-touch Protocol. + enum Valuator { + VAL_TOUCH_MAJOR = 0, // Length of the touch area. + VAL_TOUCH_MINOR, // Width of the touch area. + VAL_ORIENTATION, // Angle between the X-axis and the major axis of the + // touch area. + VAL_PRESSURE, // Pressure of the touch contact. + + // NOTE: A touch event can have multiple touch points. So when we receive a + // touch event, we need to determine which point triggered the event. + // A touch point can have both a 'Slot ID' and a 'Tracking ID', and they can + // be (in fact, usually are) different. The 'Slot ID' ranges between 0 and + // (X - 1), where X is the maximum touch points supported by the device. The + // 'Tracking ID' can be any 16-bit value. With XInput 2.0, an XI_Motion + // event that comes from a currently-unused 'Slot ID' indicates the creation + // of a new touch point, and any event that comes with a 0 value for + // 'Tracking ID' marks the removal of a touch point. During the lifetime of + // a touchpoint, we use the 'Slot ID' as its identifier. The XI_ButtonPress + // and XI_ButtonRelease events are ignored. +#if !defined(USE_XI2_MT) + VAL_SLOT_ID, // ID of the finger that triggered a touch event + // (useful when tracking multiple simultaneous + // touches) +#endif + // NOTE for XInput MT: 'Tracking ID' is provided in every touch event to + // track individual touch. 'Tracking ID' is an unsigned 32-bit value and + // is increased for each new touch. It will wrap back to 0 when reaching + // the numerical limit. + VAL_TRACKING_ID, // ID of the touch point. + + VAL_LAST_ENTRY + }; + + // Returns the ValuatorTracker singleton. + static ValuatorTracker* GetInstance(); + + // Extract the Valuator from the XEvent. Return true and the value is set + // if the Valuator is found, false and value unchanged if the Valuator + // is not found. + bool ExtractValuator(const XEvent& xev, Valuator val, float* value); + + // Normalize the Valuator with value on deviceid to fall into [0, 1]. + // *value = (*value - min_value_of_tp) / (max_value_of_tp - min_value_of_tp) + // Returns true and sets the normalized value in|value| if normalization is + // successful. Returns false and |value| is unchanged otherwise. + bool NormalizeValuator(unsigned int deviceid, Valuator val, float* value); + + // Extract the range of the Valuator. Return true if the range is available + // and written into min & max, false if the range is not available. + bool GetValuatorRange(unsigned int deviceid, + Valuator val, + float* min, + float* max); + + // Sets up the internal bookkeeping of the valuator information. It currently + // does this for touch devices only. + void SetupValuator(); + + private: + // Requirement for Singleton. + friend struct DefaultSingletonTraits<ValuatorTracker>; + + static const int kMaxDeviceNum = 128; + + // Index table to find the valuator for the Valuator on the specific device + // by valuator_lookup_[device_id][valuator]. Use 2-D array to get fast + // index at the expense of space. If the kMaxDeviceNum grows larger so that + // the space waste becomes a concern, the 2D lookup table can be replaced by a + // hash map. + signed char valuator_lookup_[kMaxDeviceNum][VAL_LAST_ENTRY]; + + // Index table to find the min & max value of the Valuator on a specific + // device. + int valuator_min_[kMaxDeviceNum][VAL_LAST_ENTRY]; + int valuator_max_[kMaxDeviceNum][VAL_LAST_ENTRY]; + + // Table to keep track of the last seen value for the specified valuator for + // a device. Defaults to 0 if the valuator was not specified in an earlier + // event. + float last_seen_valuator_[kMaxDeviceNum][VAL_LAST_ENTRY]; + + DISALLOW_COPY_AND_ASSIGN(ValuatorTracker); +}; + +} // namespace ui + +#endif // UI_BASE_X_VALUATORS_H_ @@ -294,6 +294,8 @@ 'base/x/events_x.cc', 'base/x/root_window_property_watcher_x.cc', 'base/x/root_window_property_watcher_x.h', + 'base/x/valuators.cc', + 'base/x/valuators.h', 'base/x/work_area_watcher_x.cc', 'base/x/work_area_watcher_x.h', 'base/x/x11_util.cc', |