summaryrefslogtreecommitdiffstats
path: root/ui
diff options
context:
space:
mode:
authorsadrul@chromium.org <sadrul@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2012-05-25 16:09:26 +0000
committersadrul@chromium.org <sadrul@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2012-05-25 16:09:26 +0000
commit4ba96d0e34ef8c2836045161b342516e88bcb891 (patch)
tree6495bb9c466250e927489b62ef41551c89539228 /ui
parenta9e2990775165b2780a187a5a42917a967dcb69c (diff)
downloadchromium_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.cc149
-rw-r--r--ui/base/touch/touch_factory.h67
-rw-r--r--ui/base/x/events_x.cc45
-rw-r--r--ui/base/x/valuators.cc182
-rw-r--r--ui/base/x/valuators.h113
-rw-r--r--ui/ui.gyp2
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_
diff --git a/ui/ui.gyp b/ui/ui.gyp
index 7ce9a9d..a1ed143 100644
--- a/ui/ui.gyp
+++ b/ui/ui.gyp
@@ -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',