summaryrefslogtreecommitdiffstats
path: root/ui/base/x
diff options
context:
space:
mode:
Diffstat (limited to 'ui/base/x')
-rw-r--r--ui/base/x/device_data_manager.cc423
-rw-r--r--ui/base/x/device_data_manager.h238
-rw-r--r--ui/base/x/events_x.cc535
-rw-r--r--ui/base/x/valuators.cc184
-rw-r--r--ui/base/x/valuators.h117
-rw-r--r--ui/base/x/x11_util.cc6
6 files changed, 749 insertions, 754 deletions
diff --git a/ui/base/x/device_data_manager.cc b/ui/base/x/device_data_manager.cc
new file mode 100644
index 0000000..e5b6187
--- /dev/null
+++ b/ui/base/x/device_data_manager.cc
@@ -0,0 +1,423 @@
+// Copyright 2013 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/device_data_manager.h"
+
+#include <X11/extensions/XInput.h>
+#include <X11/extensions/XInput2.h>
+#include <X11/Xlib.h>
+
+#include "base/logging.h"
+#include "base/memory/singleton.h"
+#include "base/message_pump_aurax11.h"
+#include "ui/base/events/event_constants.h"
+#include "ui/base/events/event_utils.h"
+#include "ui/base/x/device_list_cache_x.h"
+#include "ui/base/x/x11_util.h"
+
+// Copied from xserver-properties.h
+#define AXIS_LABEL_PROP_REL_HWHEEL "Rel Horiz Wheel"
+#define AXIS_LABEL_PROP_REL_WHEEL "Rel Vert Wheel"
+
+// CMT specific timings
+#define AXIS_LABEL_PROP_ABS_DBL_START_TIME "Abs Dbl Start Timestamp"
+#define AXIS_LABEL_PROP_ABS_DBL_END_TIME "Abs Dbl End Timestamp"
+
+// Ordinal values
+#define AXIS_LABEL_PROP_ABS_DBL_ORDINAL_X "Abs Dbl Ordinal X"
+#define AXIS_LABEL_PROP_ABS_DBL_ORDINAL_Y "Abs Dbl Ordinal Y"
+
+// Fling properties
+#define AXIS_LABEL_PROP_ABS_DBL_FLING_VX "Abs Dbl Fling X Velocity"
+#define AXIS_LABEL_PROP_ABS_DBL_FLING_VY "Abs Dbl Fling Y Velocity"
+#define AXIS_LABEL_PROP_ABS_FLING_STATE "Abs Fling State"
+
+#define AXIS_LABEL_PROP_ABS_FINGER_COUNT "Abs Finger Count"
+
+// Touchscreen multi-touch
+#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"
+#define AXIS_LABEL_TOUCH_TIMESTAMP "Touch Timestamp"
+
+// When you add new data types, please make sure the order here is aligned
+// with the order in the DataType enum in the header file because we assume
+// they are in sync when updating the device list (see UpdateDeviceList).
+const char* kCachedAtoms[] = {
+ AXIS_LABEL_PROP_REL_HWHEEL,
+ AXIS_LABEL_PROP_REL_WHEEL,
+ AXIS_LABEL_PROP_ABS_DBL_ORDINAL_X,
+ AXIS_LABEL_PROP_ABS_DBL_ORDINAL_Y,
+ AXIS_LABEL_PROP_ABS_DBL_START_TIME,
+ AXIS_LABEL_PROP_ABS_DBL_END_TIME,
+ AXIS_LABEL_PROP_ABS_DBL_FLING_VX,
+ AXIS_LABEL_PROP_ABS_DBL_FLING_VY,
+ AXIS_LABEL_PROP_ABS_FLING_STATE,
+ AXIS_LABEL_PROP_ABS_FINGER_COUNT,
+ AXIS_LABEL_ABS_MT_TOUCH_MAJOR,
+ AXIS_LABEL_ABS_MT_TOUCH_MINOR,
+ AXIS_LABEL_ABS_MT_ORIENTATION,
+ AXIS_LABEL_ABS_MT_PRESSURE,
+#if !defined(USE_XI2_MT)
+ AXIS_LABEL_ABS_MT_SLOT_ID,
+#endif
+ AXIS_LABEL_ABS_MT_TRACKING_ID,
+ AXIS_LABEL_TOUCH_TIMESTAMP,
+
+ NULL
+};
+
+// Constants for checking if a data type lies in the range of CMT/Touch data
+// types.
+const int kCMTDataTypeStart = ui::DeviceDataManager::DT_CMT_SCROLL_X;
+const int kCMTDataTypeEnd = ui::DeviceDataManager::DT_CMT_FINGER_COUNT;
+const int kTouchDataTypeStart = ui::DeviceDataManager::DT_TOUCH_MAJOR;
+const int kTouchDataTypeEnd = ui::DeviceDataManager::DT_TOUCH_RAW_TIMESTAMP;
+
+namespace ui {
+
+bool DeviceDataManager::IsCMTDataType(const int type) {
+ return (type >= kCMTDataTypeStart) && (type <= kCMTDataTypeEnd);
+}
+
+bool DeviceDataManager::IsTouchDataType(const int type) {
+ return (type >= kTouchDataTypeStart) && (type <= kTouchDataTypeEnd);
+}
+
+DeviceDataManager* DeviceDataManager::GetInstance() {
+ return Singleton<DeviceDataManager>::get();
+}
+
+DeviceDataManager::DeviceDataManager()
+ : natural_scroll_enabled_(false),
+ atom_cache_(ui::GetXDisplay(), kCachedAtoms) {
+ // Make sure the sizes of enum and kCachedAtoms are aligned.
+ CHECK(arraysize(kCachedAtoms) == static_cast<size_t>(DT_LAST_ENTRY) + 1);
+ UpdateDeviceList(ui::GetXDisplay());
+}
+
+DeviceDataManager::~DeviceDataManager() {
+}
+
+float DeviceDataManager::GetNaturalScrollFactor(int sourceid) const {
+ // Natural scroll is touchpad-only.
+ if (sourceid >= kMaxDeviceNum || !touchpads_[sourceid])
+ return -1.0f;
+
+ return natural_scroll_enabled_ ? 1.0f : -1.0f;
+}
+
+void DeviceDataManager::UpdateDeviceList(Display* display) {
+ cmt_devices_.reset();
+ touchpads_.reset();
+ for (int i = 0; i < kMaxDeviceNum; ++i) {
+ valuator_count_[i] = 0;
+ valuator_lookup_[i].clear();
+ data_type_lookup_[i].clear();
+ valuator_min_[i].clear();
+ valuator_max_[i].clear();
+ last_seen_valuator_[i].clear();
+ }
+
+ // Find all the touchpad devices.
+ XDeviceList dev_list =
+ ui::DeviceListCacheX::GetInstance()->GetXDeviceList(display);
+ Atom xi_touchpad = XInternAtom(display, XI_TOUCHPAD, false);
+ for (int i = 0; i < dev_list.count; ++i)
+ if (dev_list[i].type == xi_touchpad)
+ touchpads_[dev_list[i].id] = true;
+
+ // Update the structs with new valuator information
+ XIDeviceList info_list =
+ ui::DeviceListCacheX::GetInstance()->GetXI2DeviceList(display);
+ Atom atoms[DT_LAST_ENTRY];
+ for (int data_type = 0; data_type < DT_LAST_ENTRY; ++data_type)
+ atoms[data_type] = atom_cache_.GetAtom(kCachedAtoms[data_type]);
+
+ for (int i = 0; i < info_list.count; ++i) {
+ XIDeviceInfo* info = info_list.devices + i;
+
+ // We currently handle only slave, non-keyboard devices
+ if (info->use != XISlavePointer && info->use != XIFloatingSlave)
+ continue;
+
+ bool possible_cmt = false;
+ bool not_cmt = false;
+ const int deviceid = info->deviceid;
+
+ for (int j = 0; j < info->num_classes; ++j) {
+ if (info->classes[j]->type == XIValuatorClass)
+ ++valuator_count_[deviceid];
+ else if (info->classes[j]->type == XIScrollClass)
+ not_cmt = true;
+ }
+
+ // Skip devices that don't use any valuator
+ if (!valuator_count_[deviceid])
+ continue;
+
+ valuator_lookup_[deviceid].resize(DT_LAST_ENTRY, -1);
+ data_type_lookup_[deviceid].resize(
+ valuator_count_[deviceid], DT_LAST_ENTRY);
+ valuator_min_[deviceid].resize(DT_LAST_ENTRY, 0);
+ valuator_max_[deviceid].resize(DT_LAST_ENTRY, 0);
+ last_seen_valuator_[deviceid].resize(DT_LAST_ENTRY, 0);
+ for (int j = 0; j < info->num_classes; ++j) {
+ if (info->classes[j]->type != XIValuatorClass)
+ continue;
+
+ XIValuatorClassInfo* v =
+ reinterpret_cast<XIValuatorClassInfo*>(info->classes[j]);
+ for (int data_type = 0; data_type < DT_LAST_ENTRY; ++data_type) {
+ if (v->label == atoms[data_type]) {
+ valuator_lookup_[deviceid][data_type] = v->number;
+ data_type_lookup_[deviceid][v->number] = data_type;
+ valuator_min_[deviceid][data_type] = v->min;
+ valuator_max_[deviceid][data_type] = v->max;
+ if (IsCMTDataType(data_type))
+ possible_cmt = true;
+ break;
+ }
+ }
+ }
+
+ if (possible_cmt && !not_cmt)
+ cmt_devices_[deviceid] = true;
+ }
+}
+
+void DeviceDataManager::GetEventRawData(const XEvent& xev, EventData* data) {
+ if (xev.type != GenericEvent)
+ return;
+
+ XIDeviceEvent* xiev = static_cast<XIDeviceEvent*>(xev.xcookie.data);
+ if (xiev->sourceid >= kMaxDeviceNum || xiev->deviceid >= kMaxDeviceNum)
+ return;
+ data->clear();
+ const int sourceid = xiev->sourceid;
+ double* valuators = xiev->valuators.values;
+ for (int i = 0; i <= valuator_count_[sourceid]; ++i) {
+ if (XIMaskIsSet(xiev->valuators.mask, i)) {
+ int type = data_type_lookup_[sourceid][i];
+ if (type != DT_LAST_ENTRY) {
+ (*data)[type] = *valuators;
+ if (IsTouchDataType(type))
+ last_seen_valuator_[sourceid][type] = *valuators;
+ }
+ valuators++;
+ }
+ }
+}
+
+bool DeviceDataManager::GetEventData(const XEvent& xev,
+ const DataType type, double* value) {
+ if (xev.type != GenericEvent)
+ return false;
+
+ XIDeviceEvent* xiev = static_cast<XIDeviceEvent*>(xev.xcookie.data);
+ if (xiev->sourceid >= kMaxDeviceNum || xiev->deviceid >= kMaxDeviceNum)
+ return false;
+ const int sourceid = xiev->sourceid;
+ if (valuator_lookup_[sourceid].empty())
+ return false;
+
+ int val_index = valuator_lookup_[sourceid][type];
+ 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_[sourceid][type] = *value;
+ return true;
+ } else if (IsTouchDataType(type)) {
+ *value = last_seen_valuator_[sourceid][type];
+ }
+ }
+
+#if defined(USE_XI2_MT)
+ // With XInput2 MT, Tracking ID is provided in the detail field.
+ if (type == DT_TOUCH_TRACKING_ID) {
+ *value = xiev->detail;
+ return true;
+ }
+#endif
+
+ return false;
+}
+
+bool DeviceDataManager::IsTouchpadXInputEvent(
+ const base::NativeEvent& native_event) const {
+ if (native_event->type != GenericEvent)
+ return false;
+
+ XIDeviceEvent* xievent =
+ static_cast<XIDeviceEvent*>(native_event->xcookie.data);
+ if (xievent->sourceid >= kMaxDeviceNum)
+ return false;
+ return touchpads_[xievent->sourceid];
+}
+
+bool DeviceDataManager::IsCMTDeviceEvent(
+ const base::NativeEvent& native_event) const {
+ if (native_event->type != GenericEvent)
+ return false;
+
+ XIDeviceEvent* xievent =
+ static_cast<XIDeviceEvent*>(native_event->xcookie.data);
+ if (xievent->sourceid >= kMaxDeviceNum)
+ return false;
+ return cmt_devices_[xievent->sourceid];
+}
+
+bool DeviceDataManager::IsCMTGestureEvent(
+ const base::NativeEvent& native_event) const {
+ return (IsScrollEvent(native_event) ||
+ IsFlingEvent(native_event));
+}
+
+bool DeviceDataManager::HasEventData(
+ const XIDeviceEvent* xiev, const DataType type) const {
+ const int idx = valuator_lookup_[xiev->sourceid][type];
+ return (idx >= 0) && XIMaskIsSet(xiev->valuators.mask, idx);
+}
+
+bool DeviceDataManager::IsScrollEvent(
+ const base::NativeEvent& native_event) const {
+ if (!IsCMTDeviceEvent(native_event))
+ return false;
+
+ XIDeviceEvent* xiev =
+ static_cast<XIDeviceEvent*>(native_event->xcookie.data);
+ return (HasEventData(xiev, DT_CMT_SCROLL_X) ||
+ HasEventData(xiev, DT_CMT_SCROLL_Y));
+}
+
+bool DeviceDataManager::IsFlingEvent(
+ const base::NativeEvent& native_event) const {
+ if (!IsCMTDeviceEvent(native_event))
+ return false;
+
+ XIDeviceEvent* xiev =
+ static_cast<XIDeviceEvent*>(native_event->xcookie.data);
+ return (HasEventData(xiev, DT_CMT_FLING_X) &&
+ HasEventData(xiev, DT_CMT_FLING_Y) &&
+ HasEventData(xiev, DT_CMT_FLING_STATE));
+}
+
+bool DeviceDataManager::HasGestureTimes(
+ const base::NativeEvent& native_event) const {
+ if (!IsCMTDeviceEvent(native_event))
+ return false;
+
+ XIDeviceEvent* xiev =
+ static_cast<XIDeviceEvent*>(native_event->xcookie.data);
+ return (HasEventData(xiev, DT_CMT_START_TIME) &&
+ HasEventData(xiev, DT_CMT_END_TIME));
+}
+
+void DeviceDataManager::GetScrollOffsets(const base::NativeEvent& native_event,
+ float* x_offset, float* y_offset,
+ float* x_offset_ordinal,
+ float* y_offset_ordinal,
+ int* finger_count) {
+ *x_offset = 0;
+ *y_offset = 0;
+ *x_offset_ordinal = 0;
+ *y_offset_ordinal = 0;
+ *finger_count = 2;
+
+ XIDeviceEvent* xiev =
+ static_cast<XIDeviceEvent*>(native_event->xcookie.data);
+ const float natural_scroll_factor = GetNaturalScrollFactor(xiev->sourceid);
+ EventData data;
+ GetEventRawData(*native_event, &data);
+
+ if (data.find(DT_CMT_SCROLL_X) != data.end())
+ *x_offset = data[DT_CMT_SCROLL_X] * natural_scroll_factor;
+ if (data.find(DT_CMT_SCROLL_Y) != data.end())
+ *y_offset = data[DT_CMT_SCROLL_Y] * natural_scroll_factor;
+ if (data.find(DT_CMT_ORDINAL_X) != data.end())
+ *x_offset_ordinal = data[DT_CMT_ORDINAL_X] * natural_scroll_factor;
+ if (data.find(DT_CMT_ORDINAL_Y) != data.end())
+ *y_offset_ordinal = data[DT_CMT_ORDINAL_Y] * natural_scroll_factor;
+ if (data.find(DT_CMT_FINGER_COUNT) != data.end())
+ *finger_count = static_cast<int>(data[DT_CMT_FINGER_COUNT]);
+}
+
+void DeviceDataManager::GetFlingData(const base::NativeEvent& native_event,
+ float* vx, float* vy,
+ float* vx_ordinal, float* vy_ordinal,
+ bool* is_cancel) {
+ *vx = 0;
+ *vy = 0;
+ *vx_ordinal = 0;
+ *vy_ordinal = 0;
+ *is_cancel = false;
+
+ XIDeviceEvent* xiev =
+ static_cast<XIDeviceEvent*>(native_event->xcookie.data);
+ const float natural_scroll_factor = GetNaturalScrollFactor(xiev->sourceid);
+ EventData data;
+ GetEventRawData(*native_event, &data);
+
+ if (data.find(DT_CMT_FLING_X) != data.end())
+ *vx = data[DT_CMT_FLING_X] * natural_scroll_factor;
+ if (data.find(DT_CMT_FLING_Y) != data.end())
+ *vy = data[DT_CMT_FLING_Y] * natural_scroll_factor;
+ if (data.find(DT_CMT_FLING_STATE) != data.end())
+ *is_cancel = !!static_cast<unsigned int>(data[DT_CMT_FLING_STATE]);
+ if (data.find(DT_CMT_ORDINAL_X) != data.end())
+ *vx_ordinal = data[DT_CMT_ORDINAL_X] * natural_scroll_factor;
+ if (data.find(DT_CMT_ORDINAL_Y) != data.end())
+ *vy_ordinal = data[DT_CMT_ORDINAL_Y] * natural_scroll_factor;
+}
+
+void DeviceDataManager::GetGestureTimes(const base::NativeEvent& native_event,
+ double* start_time,
+ double* end_time) {
+ *start_time = 0;
+ *end_time = 0;
+
+ EventData data;
+ GetEventRawData(*native_event, &data);
+
+ if (data.find(DT_CMT_START_TIME) != data.end())
+ *start_time = data[DT_CMT_START_TIME];
+ if (data.find(DT_CMT_END_TIME) != data.end())
+ *end_time = data[DT_CMT_END_TIME];
+}
+
+bool DeviceDataManager::NormalizeData(unsigned int deviceid,
+ const DataType type,
+ double* value) {
+ double max_value;
+ double min_value;
+ if (GetDataRange(deviceid, type, &min_value, &max_value)) {
+ *value = (*value - min_value) / (max_value - min_value);
+ DCHECK(*value >= 0.0 && *value <= 1.0);
+ return true;
+ }
+ return false;
+}
+
+bool DeviceDataManager::GetDataRange(unsigned int deviceid,
+ const DataType type,
+ double* min, double* max) {
+ if (deviceid >= static_cast<unsigned int>(kMaxDeviceNum))
+ return false;
+ if (valuator_lookup_[deviceid][type] >= 0) {
+ *min = valuator_min_[deviceid][type];
+ *max = valuator_max_[deviceid][type];
+ return true;
+ }
+ return false;
+}
+
+} // namespace ui
diff --git a/ui/base/x/device_data_manager.h b/ui/base/x/device_data_manager.h
new file mode 100644
index 0000000..27f468a
--- /dev/null
+++ b/ui/base/x/device_data_manager.h
@@ -0,0 +1,238 @@
+// Copyright 2013 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_DEVICE_DATA_MANAGER_H_
+#define UI_BASE_X_DEVICE_DATA_MANAGER_H_
+
+#include <X11/extensions/XInput2.h>
+
+#include <bitset>
+#include <map>
+#include <vector>
+
+#include "base/basictypes.h"
+#include "base/event_types.h"
+#include "ui/base/events/event_constants.h"
+#include "ui/base/ui_export.h"
+#include "ui/base/x/x11_atom_cache.h"
+
+template <typename T> struct DefaultSingletonTraits;
+
+typedef union _XEvent XEvent;
+
+namespace ui {
+
+// A class that extracts and tracks the input events data. It currently handles
+// mouse, touchpad and touchscreen devices.
+class UI_EXPORT DeviceDataManager {
+ public:
+ // Enumerate additional data that one might be interested on an input event,
+ // which are usually wrapped in X valuators. If you modify any of this,
+ // make sure to update the kCachedAtoms data structure in the source file
+ // and the k*Type[Start/End] constants used by IsCMTDataType and
+ // IsTouchDataType.
+ enum DataType {
+ // Define the valuators used the CrOS CMT driver. Used by mice and CrOS
+ // touchpads.
+ DT_CMT_SCROLL_X = 0, // Scroll amount on the X (horizontal) direction.
+ DT_CMT_SCROLL_Y, // Scroll amount on the Y (vertical) direction.
+ DT_CMT_ORDINAL_X, // Original (unaccelerated) value on the X direction.
+ // Can be used both for scrolls and flings.
+ DT_CMT_ORDINAL_Y, // Original (unaccelerated) value on the Y direction.
+ // Can be used both for scrolls and flings.
+ DT_CMT_START_TIME, // Gesture start time.
+ DT_CMT_END_TIME, // Gesture end time.
+ DT_CMT_FLING_X, // Fling amount on the X (horizontal) direction.
+ DT_CMT_FLING_Y, // Fling amount on the Y (vertical) direction.
+ DT_CMT_FLING_STATE, // The state of fling gesture (whether the user just
+ // start flinging or that he/she taps down).
+ DT_CMT_FINGER_COUNT, // Finger counts in the current gesture. A same type
+ // of gesture can have very different meanings based
+ // on that (e.g. 2f scroll v.s. 3f swipe).
+
+ // End of CMT data types.
+ // Beginning of touch data types.
+
+ // Define the valuators following the Multi-touch Protocol. Used by
+ // touchscreen devices.
+ DT_TOUCH_MAJOR, // Length of the touch area.
+ DT_TOUCH_MINOR, // Width of the touch area.
+ DT_TOUCH_ORIENTATION, // Angle between the X-axis and the major axis of the
+ // touch area.
+ DT_TOUCH_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)
+ DT_TOUCH_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.
+ DT_TOUCH_TRACKING_ID, // ID of the touch point.
+
+ // Kernel timestamp from touch screen (if available).
+ DT_TOUCH_RAW_TIMESTAMP,
+
+ // End of touch data types.
+
+ DT_LAST_ENTRY // This must come last.
+ };
+
+ // Data struct to store extracted data from an input event.
+ typedef std::map<int, double> EventData;
+
+ // We use int because enums can be casted to ints but not vice versa.
+ static bool IsCMTDataType(const int type);
+ static bool IsTouchDataType(const int type);
+
+ // Returns the DeviceDataManager singleton.
+ static DeviceDataManager* GetInstance();
+
+ // Natural scroll setter/getter.
+ bool natural_scroll_enabled() const { return natural_scroll_enabled_; }
+ void set_natural_scroll_enabled(bool enabled) {
+ natural_scroll_enabled_ = enabled;
+ }
+
+ // Get the natural scroll direction multiplier (1.0f or -1.0f).
+ float GetNaturalScrollFactor(int sourceid) const;
+
+ // Updates the list of devices.
+ void UpdateDeviceList(Display* display);
+
+ // Get all event data in one pass. We extract only data types that we know
+ // about (defined in enum DataType). The data is not processed (e.g. not
+ // filled in by cached values) as in GetEventData.
+ void GetEventRawData(const XEvent& xev, EventData* data);
+
+ // Get a datum of the specified type. Return true and the value
+ // is updated if the data is found, false and value unchanged if the data is
+ // not found. In the case of MT-B/XI2.2, the value can come from a previously
+ // cached one (see the comment above last_seen_valuator_).
+ bool GetEventData(const XEvent& xev, const DataType type, double* value);
+
+ // Check if the event comes from touchpad devices.
+ bool IsTouchpadXInputEvent(const base::NativeEvent& native_event) const;
+
+ // Check if the event comes from devices running CMT driver or using
+ // CMT valuators (e.g. mouses). Note that doesn't necessarily mean the event
+ // is a CMT event (e.g. it could be a mouse pointer move).
+ bool IsCMTDeviceEvent(const base::NativeEvent& native_event) const;
+
+ // Check if the event is one of the CMT gesture events (scroll, fling,
+ // metrics etc.).
+ bool IsCMTGestureEvent(const base::NativeEvent& native_event) const;
+
+ // Returns true if the event is of the specific type, false if not.
+ bool IsScrollEvent(const base::NativeEvent& native_event) const;
+ bool IsFlingEvent(const base::NativeEvent& native_event) const;
+
+ // Returns true if the event has CMT start/end timestamps.
+ bool HasGestureTimes(const base::NativeEvent& native_event) const;
+
+ // Extract data from a scroll event (a motion event with the necessary
+ // valuators). User must first verify the event type with IsScrollEvent.
+ // Pointers shouldn't be NULL.
+ void GetScrollOffsets(const base::NativeEvent& native_event,
+ float* x_offset,
+ float* y_offset,
+ float* x_offset_ordinal,
+ float* y_offset_ordinal,
+ int* finger_count);
+
+ // Extract data from a fling event. User must first verify the event type
+ // with IsFlingEvent. Pointers shouldn't be NULL.
+ void GetFlingData(const base::NativeEvent& native_event,
+ float* vx,
+ float* vy,
+ float* vx_ordinal,
+ float* vy_ordinal,
+ bool* is_cancel);
+
+ // Extract the start/end timestamps from CMT events. User must first verify
+ // the event with HasGestureTimes. Pointers shouldn't be NULL.
+ void GetGestureTimes(const base::NativeEvent& native_event,
+ double* start_time,
+ double* end_time);
+
+ // Normalize the data 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 NormalizeData(unsigned int deviceid,
+ const DataType type,
+ double* value);
+
+ // Extract the range of the data type. Return true if the range is available
+ // and written into min & max, false if the range is not available.
+ bool GetDataRange(unsigned int deviceid,
+ const DataType type,
+ double* min,
+ double* max);
+
+ private:
+ // Requirement for Singleton.
+ friend struct DefaultSingletonTraits<DeviceDataManager>;
+
+ DeviceDataManager();
+ ~DeviceDataManager();
+
+ // Check if an XI event contains data of the specified type.
+ bool HasEventData(const XIDeviceEvent* xiev, const DataType type) const;
+
+ static const int kMaxDeviceNum = 128;
+ bool natural_scroll_enabled_;
+
+ // A quick lookup table for determining if events from the pointer device
+ // should be processed.
+ std::bitset<kMaxDeviceNum> cmt_devices_;
+ std::bitset<kMaxDeviceNum> touchpads_;
+
+ // Number of valuators on the specific device.
+ int valuator_count_[kMaxDeviceNum];
+
+ // Index table to find the valuator for DataType on the specific device
+ // by valuator_lookup_[device_id][data_type].
+ std::vector<int> valuator_lookup_[kMaxDeviceNum];
+
+ // Index table to find the DataType for valuator on the specific device
+ // by data_type_lookup_[device_id][valuator].
+ std::vector<int> data_type_lookup_[kMaxDeviceNum];
+
+ // Index table to find the min & max value of the Valuator on a specific
+ // device.
+ std::vector<double> valuator_min_[kMaxDeviceNum];
+ std::vector<double> valuator_max_[kMaxDeviceNum];
+
+ // 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. 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. We currently use this only on touchscreen
+ // devices.
+ std::vector<double> last_seen_valuator_[kMaxDeviceNum];
+
+ // X11 atoms cache.
+ X11AtomCache atom_cache_;
+
+ DISALLOW_COPY_AND_ASSIGN(DeviceDataManager);
+};
+
+} // namespace ui
+
+#endif // UI_BASE_X_DEVICE_DATA_MANAGER_H_
diff --git a/ui/base/x/events_x.cc b/ui/base/x/events_x.cc
index 6c50da0..4a37457 100644
--- a/ui/base/x/events_x.cc
+++ b/ui/base/x/events_x.cc
@@ -16,8 +16,8 @@
#include "ui/base/events/event_utils.h"
#include "ui/base/keycodes/keyboard_code_conversion_x.h"
#include "ui/base/touch/touch_factory_x11.h"
+#include "ui/base/x/device_data_manager.h"
#include "ui/base/x/device_list_cache_x.h"
-#include "ui/base/x/valuators.h"
#include "ui/base/x/x11_atom_cache.h"
#include "ui/base/x/x11_util.h"
#include "ui/gfx/display.h"
@@ -25,31 +25,6 @@
#include "ui/gfx/rect.h"
#include "ui/gfx/screen.h"
-// Copied from xserver-properties.h
-#define AXIS_LABEL_PROP_REL_HWHEEL "Rel Horiz Wheel"
-#define AXIS_LABEL_PROP_REL_WHEEL "Rel Vert Wheel"
-
-// CMT specific timings
-#define AXIS_LABEL_PROP_ABS_START_TIME "Abs Start Timestamp"
-#define AXIS_LABEL_PROP_ABS_END_TIME "Abs End Timestamp"
-
-// Ordinal values
-#define AXIS_LABEL_PROP_ABS_DBL_ORDINAL_X "Abs Dbl Ordinal X"
-#define AXIS_LABEL_PROP_ABS_DBL_ORDINAL_Y "Abs Dbl Ordinal Y"
-
-// Fling properties
-#define AXIS_LABEL_PROP_ABS_FLING_X "Abs Fling X Velocity"
-#define AXIS_LABEL_PROP_ABS_FLING_Y "Abs Fling Y Velocity"
-#define AXIS_LABEL_PROP_ABS_FLING_STATE "Abs Fling State"
-
-#define AXIS_LABEL_PROP_ABS_FINGER_COUNT "Abs Finger Count"
-
-// New versions of the valuators, with double values instead of fixed point.
-#define AXIS_LABEL_PROP_ABS_DBL_START_TIME "Abs Dbl Start Timestamp"
-#define AXIS_LABEL_PROP_ABS_DBL_END_TIME "Abs Dbl End Timestamp"
-#define AXIS_LABEL_PROP_ABS_DBL_FLING_VX "Abs Dbl Fling X Velocity"
-#define AXIS_LABEL_PROP_ABS_DBL_FLING_VY "Abs Dbl Fling Y Velocity"
-
namespace {
// Scroll amount for each wheelscroll event. 53 is also the value used for GTK+.
@@ -58,24 +33,6 @@ const int kWheelScrollAmount = 53;
const int kMinWheelButton = 4;
const int kMaxWheelButton = 7;
-const char* kCMTCachedAtoms[] = {
- AXIS_LABEL_PROP_ABS_DBL_ORDINAL_X,
- AXIS_LABEL_PROP_ABS_DBL_ORDINAL_Y,
- AXIS_LABEL_PROP_REL_HWHEEL,
- AXIS_LABEL_PROP_REL_WHEEL,
- AXIS_LABEL_PROP_ABS_START_TIME,
- AXIS_LABEL_PROP_ABS_DBL_START_TIME,
- AXIS_LABEL_PROP_ABS_END_TIME,
- AXIS_LABEL_PROP_ABS_DBL_END_TIME,
- AXIS_LABEL_PROP_ABS_FLING_X,
- AXIS_LABEL_PROP_ABS_FLING_Y,
- AXIS_LABEL_PROP_ABS_DBL_FLING_VX,
- AXIS_LABEL_PROP_ABS_DBL_FLING_VY,
- AXIS_LABEL_PROP_ABS_FLING_STATE,
- AXIS_LABEL_PROP_ABS_FINGER_COUNT,
- NULL
-};
-
// A workaround for some incorrect implemented input drivers:
// Ignore their mouse input valuators.
bool IgnoreMouseValuators() {
@@ -89,373 +46,6 @@ bool IgnoreMouseValuators() {
return ignore_valuators;
}
-// A class to support the detection of scroll events, using X11 valuators.
-class CMTEventData {
- public:
- // Returns the ScrollEventData singleton.
- static CMTEventData* GetInstance() {
- return Singleton<CMTEventData>::get();
- }
-
- // Updates the list of devices.
- void UpdateDeviceList(Display* display) {
- cmt_devices_.reset();
- touchpads_.reset();
- device_to_valuators_.clear();
-
-#if defined(USE_XI2_MT)
- // Find all the touchpad devices.
- XDeviceList dev_list =
- ui::DeviceListCacheX::GetInstance()->GetXDeviceList(display);
- Atom xi_touchpad = XInternAtom(display, XI_TOUCHPAD, false);
- for (int i = 0; i < dev_list.count; ++i)
- if (dev_list[i].type == xi_touchpad)
- touchpads_[dev_list[i].id] = true;
-
- XIDeviceList info_list =
- ui::DeviceListCacheX::GetInstance()->GetXI2DeviceList(display);
- Atom x_axis = atom_cache_.GetAtom(AXIS_LABEL_PROP_REL_HWHEEL);
- Atom y_axis = atom_cache_.GetAtom(AXIS_LABEL_PROP_REL_WHEEL);
- Atom x_ordinal = atom_cache_.GetAtom(AXIS_LABEL_PROP_ABS_DBL_ORDINAL_X);
- Atom y_ordinal = atom_cache_.GetAtom(AXIS_LABEL_PROP_ABS_DBL_ORDINAL_Y);
- Atom start_time = atom_cache_.GetAtom(AXIS_LABEL_PROP_ABS_START_TIME);
- Atom start_time_dbl =
- atom_cache_.GetAtom(AXIS_LABEL_PROP_ABS_DBL_START_TIME);
- Atom end_time = atom_cache_.GetAtom(AXIS_LABEL_PROP_ABS_END_TIME);
- Atom end_time_dbl = atom_cache_.GetAtom(AXIS_LABEL_PROP_ABS_DBL_END_TIME);
- Atom fling_vx = atom_cache_.GetAtom(AXIS_LABEL_PROP_ABS_FLING_X);
- Atom fling_vx_dbl = atom_cache_.GetAtom(AXIS_LABEL_PROP_ABS_DBL_FLING_VX);
- Atom fling_vy = atom_cache_.GetAtom(AXIS_LABEL_PROP_ABS_FLING_Y);
- Atom fling_vy_dbl = atom_cache_.GetAtom(AXIS_LABEL_PROP_ABS_DBL_FLING_VY);
- Atom fling_state = atom_cache_.GetAtom(AXIS_LABEL_PROP_ABS_FLING_STATE);
- Atom finger_count = atom_cache_.GetAtom(AXIS_LABEL_PROP_ABS_FINGER_COUNT);
-
- for (int i = 0; i < info_list.count; ++i) {
- XIDeviceInfo* info = info_list.devices + i;
-
- if (info->use != XISlavePointer && info->use != XIFloatingSlave)
- continue;
-
- Valuators valuators;
- bool is_cmt = false;
- for (int j = 0; j < info->num_classes; ++j) {
- if (info->classes[j]->type == XIScrollClass) {
- is_cmt = false;
- break;
- }
- if (info->classes[j]->type != XIValuatorClass)
- continue;
-
- XIValuatorClassInfo* v =
- reinterpret_cast<XIValuatorClassInfo*>(info->classes[j]);
- int number = v->number;
- if (number > valuators.max)
- valuators.max = number;
- if (v->label == x_axis) {
- valuators.scroll_x = number;
- is_cmt = true;
- } else if (v->label == y_axis) {
- valuators.scroll_y = number;
- is_cmt = true;
- } else if (v->label == x_ordinal) {
- valuators.ordinal_x = number;
- is_cmt = true;
- } else if (v->label == y_ordinal) {
- valuators.ordinal_y = number;
- is_cmt = true;
- } else if (v->label == finger_count) {
- valuators.finger_count = number;
- is_cmt = true;
- } else if (v->label == start_time) {
- valuators.start_time = number;
- is_cmt = true;
- } else if (v->label == start_time_dbl) {
- valuators.start_time_dbl = number;
- is_cmt = true;
- } else if (v->label == end_time) {
- valuators.end_time = number;
- is_cmt = true;
- } else if (v->label == end_time_dbl) {
- valuators.end_time_dbl = number;
- is_cmt = true;
- } else if (v->label == fling_vx) {
- valuators.fling_vx = number;
- is_cmt = true;
- } else if (v->label == fling_vx_dbl) {
- valuators.fling_vx_dbl = number;
- is_cmt = true;
- } else if (v->label == fling_vy) {
- valuators.fling_vy = number;
- is_cmt = true;
- } else if (v->label == fling_vy_dbl) {
- valuators.fling_vy_dbl = number;
- is_cmt = true;
- } else if (v->label == fling_state) {
- valuators.fling_state = number;
- is_cmt = true;
- }
- }
- if (is_cmt) {
- // Double valuators override fixed point ones.
- if (valuators.start_time_dbl >= 0)
- valuators.start_time = -1;
- if (valuators.end_time_dbl >= 0)
- valuators.end_time = -1;
- if (valuators.fling_vx_dbl >= 0)
- valuators.fling_vx = -1;
- if (valuators.fling_vy_dbl >= 0)
- valuators.fling_vy = -1;
- device_to_valuators_[info->deviceid] = valuators;
- cmt_devices_[info->deviceid] = true;
- }
- }
-#endif // defined(USE_XI2_MT)
- }
-
- bool natural_scroll_enabled() const { return natural_scroll_enabled_; }
- void set_natural_scroll_enabled(bool enabled) {
- natural_scroll_enabled_ = enabled;
- }
-
- bool IsTouchpadXInputEvent(const base::NativeEvent& native_event) {
- if (native_event->type != GenericEvent)
- return false;
-
- XIDeviceEvent* xievent =
- static_cast<XIDeviceEvent*>(native_event->xcookie.data);
- return touchpads_[xievent->sourceid];
- }
-
- float GetNaturalScrollFactor(int sourceid) {
- // Natural scroll is touchpad-only.
- if (!touchpads_[sourceid])
- return -1.0f;
-
- return natural_scroll_enabled_ ? 1.0f : -1.0f;
- }
-
- // Returns true if this is a scroll event (a motion event with the necessary
- // valuators. Also returns the offsets. |x_offset| and |y_offset| can be
- // NULL.
- bool GetScrollOffsets(const XEvent& xev,
- float* x_offset,
- float* y_offset,
- float* x_offset_ordinal,
- float* y_offset_ordinal,
- int* finger_count) {
- XIDeviceEvent* xiev = static_cast<XIDeviceEvent*>(xev.xcookie.data);
-
- if (x_offset)
- *x_offset = 0;
- if (y_offset)
- *y_offset = 0;
- if (x_offset_ordinal)
- *x_offset_ordinal = 0;
- if (y_offset_ordinal)
- *y_offset_ordinal = 0;
- if (finger_count)
- *finger_count = 2;
-
- const int sourceid = xiev->sourceid;
- if (!cmt_devices_[sourceid])
- return false;
-
- const float natural_scroll_factor = GetNaturalScrollFactor(sourceid);
- const Valuators v = device_to_valuators_[sourceid];
- const bool has_x_offset = XIMaskIsSet(xiev->valuators.mask, v.scroll_x);
- const bool has_y_offset = XIMaskIsSet(xiev->valuators.mask, v.scroll_y);
- const bool is_scroll = has_x_offset || has_y_offset;
-
- if (!is_scroll || (!x_offset && !y_offset))
- return is_scroll;
-
- double* valuators = xiev->valuators.values;
- for (int i = 0; i <= v.max; ++i) {
- if (XIMaskIsSet(xiev->valuators.mask, i)) {
- if (x_offset && v.scroll_x == i)
- *x_offset = *valuators * natural_scroll_factor;
- else if (y_offset && v.scroll_y == i)
- *y_offset = *valuators * natural_scroll_factor;
- else if (x_offset_ordinal && v.ordinal_x == i)
- *x_offset_ordinal = *valuators * natural_scroll_factor;
- else if (y_offset_ordinal && v.ordinal_y == i)
- *y_offset_ordinal = *valuators * natural_scroll_factor;
- else if (finger_count && v.finger_count == i)
- *finger_count = static_cast<int>(*valuators);
- valuators++;
- }
- }
-
- return true;
- }
-
- bool GetFlingData(const XEvent& xev,
- float* vx, float* vy,
- float* vx_ordinal, float* vy_ordinal,
- bool* is_cancel) {
- XIDeviceEvent* xiev = static_cast<XIDeviceEvent*>(xev.xcookie.data);
-
- if (vx)
- *vx = 0;
- if (vy)
- *vy = 0;
- if (vx_ordinal)
- *vx_ordinal = 0;
- if (vy_ordinal)
- *vy_ordinal = 0;
- if (is_cancel)
- *is_cancel = false;
-
- const int sourceid = xiev->sourceid;
- if (!cmt_devices_[sourceid])
- return false;
-
- const float natural_scroll_factor = GetNaturalScrollFactor(sourceid);
- const Valuators v = device_to_valuators_[sourceid];
- if ((!XIMaskIsSet(xiev->valuators.mask, v.fling_vx) &&
- !XIMaskIsSet(xiev->valuators.mask, v.fling_vx_dbl)) ||
- (!XIMaskIsSet(xiev->valuators.mask, v.fling_vy) &&
- !XIMaskIsSet(xiev->valuators.mask, v.fling_vy_dbl)) ||
- !XIMaskIsSet(xiev->valuators.mask, v.fling_state))
- return false;
-
- double* valuators = xiev->valuators.values;
- for (int i = 0; i <= v.max; ++i) {
- if (XIMaskIsSet(xiev->valuators.mask, i)) {
- // Convert values to unsigned ints representing ms before storing them,
- // as that is how they were encoded before conversion to doubles.
- if (vx && v.fling_vx_dbl == i) {
- *vx = natural_scroll_factor * *valuators;
- } else if (vx && v.fling_vx == i) {
- *vx = natural_scroll_factor *
- static_cast<double>(static_cast<int>(*valuators)) / 1000.0f;
- } else if (vy && v.fling_vy_dbl == i) {
- *vy = natural_scroll_factor * *valuators;
- } else if (vy && v.fling_vy == i) {
- *vy = natural_scroll_factor *
- static_cast<double>(static_cast<int>(*valuators)) / 1000.0f;
- } else if (is_cancel && v.fling_state == i) {
- *is_cancel = !!static_cast<unsigned int>(*valuators);
- } else if (vx_ordinal && v.ordinal_x == i) {
- *vx_ordinal = *valuators * natural_scroll_factor;
- } else if (vy_ordinal && v.ordinal_y == i) {
- *vy_ordinal = *valuators * natural_scroll_factor;
- }
- valuators++;
- }
- }
-
- return true;
- }
-
- bool GetGestureTimes(const XEvent& xev,
- double* start_time,
- double* end_time) {
- *start_time = 0;
- *end_time = 0;
-
- XIDeviceEvent* xiev = static_cast<XIDeviceEvent*>(xev.xcookie.data);
- if (!cmt_devices_[xiev->sourceid])
- return false;
-
- Valuators v = device_to_valuators_[xiev->sourceid];
- if ((!XIMaskIsSet(xiev->valuators.mask, v.start_time) &&
- !XIMaskIsSet(xiev->valuators.mask, v.start_time_dbl)) ||
- (!XIMaskIsSet(xiev->valuators.mask, v.end_time) &&
- !XIMaskIsSet(xiev->valuators.mask, v.end_time_dbl)))
- return false;
-
- double* valuators = xiev->valuators.values;
- for (int i = 0; i <= v.max; ++i) {
- if (XIMaskIsSet(xiev->valuators.mask, i)) {
- if (v.start_time_dbl == i) {
- *start_time = *valuators;
- } else if (v.start_time == i) {
- // Convert values to unsigned ints representing ms before storing
- // them, as that is how they were encoded before conversion
- // to doubles.
- *start_time =
- static_cast<double>(
- static_cast<unsigned int>(*valuators)) / 1000;
- } else if (v.end_time_dbl == i) {
- *end_time = *valuators;
- } else if (v.end_time == i) {
- // Convert values to unsigned ints representing ms before storing
- // them, as that is how they were encoded before conversion
- // to doubles.
- *end_time =
- static_cast<double>(
- static_cast<unsigned int>(*valuators)) / 1000;
- }
- valuators++;
- }
- }
-
- return true;
- }
-
- private:
- // Requirement for Singleton
- friend struct DefaultSingletonTraits<CMTEventData>;
-
- struct Valuators {
- int max;
- int scroll_x;
- int scroll_y;
- int ordinal_x;
- int ordinal_y;
- int finger_count;
- int start_time;
- int end_time;
- int fling_vx;
- int fling_vy;
- int fling_state;
- // *_dbl valuators take precedence over the fixed precision versions.
- int start_time_dbl;
- int end_time_dbl;
- int fling_vx_dbl;
- int fling_vy_dbl;
-
- Valuators()
- : max(-1),
- scroll_x(-1),
- scroll_y(-1),
- ordinal_x(-1),
- ordinal_y(-1),
- finger_count(-1),
- start_time(-1),
- end_time(-1),
- fling_vx(-1),
- fling_vy(-1),
- fling_state(-1),
- start_time_dbl(-1),
- end_time_dbl(-1),
- fling_vx_dbl(-1),
- fling_vy_dbl(-1) {
- }
-
- };
-
- CMTEventData()
- : natural_scroll_enabled_(false),
- atom_cache_(ui::GetXDisplay(), kCMTCachedAtoms) {
- UpdateDeviceList(ui::GetXDisplay());
- }
-
- ~CMTEventData() {}
-
- // A quick lookup table for determining if events from the pointer device
- // should be processed.
- static const int kMaxDeviceNum = 128;
- bool natural_scroll_enabled_;
- std::bitset<kMaxDeviceNum> cmt_devices_;
- std::bitset<kMaxDeviceNum> touchpads_;
- std::map<int, Valuators> device_to_valuators_;
- ui::X11AtomCache atom_cache_;
-
- DISALLOW_COPY_AND_ASSIGN(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.
@@ -540,8 +130,8 @@ bool TouchEventIsGeneratedHack(const base::NativeEvent& native_event) {
double radius = ui::GetTouchRadiusX(native_event), min, max;
unsigned int deviceid =
static_cast<XIDeviceEvent*>(native_event->xcookie.data)->sourceid;
- if (!ui::ValuatorTracker::GetInstance()->GetValuatorRange(
- deviceid, ui::ValuatorTracker::VAL_TOUCH_MAJOR, &min, &max)) {
+ if (!ui::DeviceDataManager::GetInstance()->GetDataRange(
+ deviceid, ui::DeviceDataManager::DT_TOUCH_MAJOR, &min, &max)) {
return false;
}
@@ -645,11 +235,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();
+ ui::DeviceDataManager* manager = ui::DeviceDataManager::GetInstance();
double slot;
- if (!valuators->ExtractValuator(
- *native_event, ui::ValuatorTracker::VAL_SLOT_ID, &slot))
+ if (!manager->GetEventData(
+ *native_event, ui::DeviceDataManager::DT_TOUCH_SLOT_ID, &slot))
return ui::ET_UNKNOWN;
if (!factory->IsSlotUsed(slot)) {
@@ -658,8 +248,8 @@ ui::EventType GetTouchEventType(const base::NativeEvent& native_event) {
}
double tracking;
- if (!valuators->ExtractValuator(
- *native_event, ui::ValuatorTracker::VAL_TRACKING_ID, &tracking))
+ if (!manager->GetEventData(
+ *native_event, ui::DeviceDataManager::DT_TOUCH_TRACKING_ID, &tracking))
return ui::ET_UNKNOWN;
if (tracking == 0l) {
@@ -672,9 +262,9 @@ ui::EventType GetTouchEventType(const base::NativeEvent& native_event) {
}
double GetTouchParamFromXEvent(XEvent* xev,
- ui::ValuatorTracker::Valuator val,
+ ui::DeviceDataManager::DataType val,
double default_value) {
- ui::ValuatorTracker::GetInstance()->ExtractValuator(
+ ui::DeviceDataManager::GetInstance()->GetEventData(
*xev, val, &default_value);
return default_value;
}
@@ -692,9 +282,8 @@ namespace ui {
void UpdateDeviceList() {
Display* display = GetXDisplay();
DeviceListCacheX::GetInstance()->UpdateDeviceList(display);
- CMTEventData::GetInstance()->UpdateDeviceList(display);
TouchFactory::GetInstance()->UpdateDeviceList(display);
- ValuatorTracker::GetInstance()->SetupValuator();
+ DeviceDataManager::GetInstance()->UpdateDeviceList(display);
}
EventType EventTypeFromNative(const base::NativeEvent& native_event) {
@@ -752,8 +341,8 @@ EventType EventTypeFromNative(const base::NativeEvent& native_event) {
bool is_cancel;
if (GetFlingData(native_event, NULL, NULL, NULL, NULL, &is_cancel)) {
return is_cancel ? ET_SCROLL_FLING_CANCEL : ET_SCROLL_FLING_START;
- } else if (GetScrollOffsets(
- native_event, NULL, NULL, NULL, NULL, NULL)) {
+ } else if (DeviceDataManager::GetInstance()->IsScrollEvent(
+ native_event)) {
return IsTouchpadEvent(native_event) ? ET_SCROLL : ET_MOUSEWHEEL;
} else if (GetButtonMaskForX2Event(xievent)) {
return ET_MOUSE_DRAGGED;
@@ -849,8 +438,8 @@ base::TimeDelta EventTimeFromNative(const base::NativeEvent& native_event) {
if (GetGestureTimes(native_event, &start, &end)) {
// If the driver supports gesture times, use them.
return base::TimeDelta::FromMicroseconds(end * 1000000);
- } else if (ValuatorTracker::GetInstance()->ExtractValuator(*native_event,
- ValuatorTracker::VAL_TOUCH_RAW_TIMESTAMP, &touch_timestamp)) {
+ } else if (DeviceDataManager::GetInstance()->GetEventData(*native_event,
+ DeviceDataManager::DT_TOUCH_RAW_TIMESTAMP, &touch_timestamp)) {
return base::TimeDelta::FromMicroseconds(touch_timestamp * 1000000);
} else {
XIDeviceEvent* xide =
@@ -998,10 +587,9 @@ int GetChangedMouseButtonFlagsFromNative(
}
gfx::Vector2d GetMouseWheelOffset(const base::NativeEvent& native_event) {
- float x_offset = 0;
- float y_offset = 0;
- if (native_event->type == GenericEvent &&
- GetScrollOffsets(native_event, &x_offset, &y_offset, NULL, NULL, NULL)) {
+ float x_offset, y_offset;
+ if (GetScrollOffsets(
+ native_event, &x_offset, &y_offset, NULL, NULL, NULL)) {
return gfx::Vector2d(static_cast<int>(x_offset),
static_cast<int>(y_offset));
}
@@ -1030,12 +618,12 @@ int GetTouchId(const base::NativeEvent& xev) {
return slot;
}
- ui::ValuatorTracker* valuators = ui::ValuatorTracker::GetInstance();
+ ui::DeviceDataManager* manager = ui::DeviceDataManager::GetInstance();
#if defined(USE_XI2_MT)
double tracking_id;
- if (!valuators->ExtractValuator(
- *xev, ui::ValuatorTracker::VAL_TRACKING_ID, &tracking_id)) {
+ if (!manager->GetEventData(
+ *xev, ui::DeviceDataManager::DT_TOUCH_TRACKING_ID, &tracking_id)) {
LOG(ERROR) << "Could not get the slot ID for the event. Using 0.";
} else {
slot = factory->GetSlotForTrackingID(tracking_id);
@@ -1046,8 +634,8 @@ int GetTouchId(const base::NativeEvent& xev) {
}
}
#else
- if (!valuators->ExtractValuator(
- *xev, ui::ValuatorTracker::VAL_SLOT_ID, &slot))
+ if (!manager->GetEventData(
+ *xev, ui::DeviceDataManager::DT_TOUCH_SLOT_ID, &slot))
LOG(ERROR) << "Could not get the slot ID for the event. Using 0.";
#endif
return slot;
@@ -1055,28 +643,28 @@ int GetTouchId(const base::NativeEvent& xev) {
float GetTouchRadiusX(const base::NativeEvent& native_event) {
return GetTouchParamFromXEvent(native_event,
- ui::ValuatorTracker::VAL_TOUCH_MAJOR, 0.0) / 2.0;
+ ui::DeviceDataManager::DT_TOUCH_MAJOR, 0.0) / 2.0;
}
float GetTouchRadiusY(const base::NativeEvent& native_event) {
return GetTouchParamFromXEvent(native_event,
- ui::ValuatorTracker::VAL_TOUCH_MINOR, 0.0) / 2.0;
+ ui::DeviceDataManager::DT_TOUCH_MINOR, 0.0) / 2.0;
}
float GetTouchAngle(const base::NativeEvent& native_event) {
return GetTouchParamFromXEvent(native_event,
- ui::ValuatorTracker::VAL_ORIENTATION, 0.0) / 2.0;
+ ui::DeviceDataManager::DT_TOUCH_ORIENTATION, 0.0) / 2.0;
}
float GetTouchForce(const base::NativeEvent& native_event) {
double force = 0.0;
force = GetTouchParamFromXEvent(native_event,
- ui::ValuatorTracker::VAL_PRESSURE, 0.0);
+ ui::DeviceDataManager::DT_TOUCH_PRESSURE, 0.0);
unsigned int deviceid =
static_cast<XIDeviceEvent*>(native_event->xcookie.data)->sourceid;
// Force is normalized to fall into [0, 1]
- if (!ui::ValuatorTracker::GetInstance()->NormalizeValuator(
- deviceid, ui::ValuatorTracker::VAL_PRESSURE, &force))
+ if (!ui::DeviceDataManager::GetInstance()->NormalizeData(
+ deviceid, ui::DeviceDataManager::DT_TOUCH_PRESSURE, &force))
force = 0.0;
return force;
}
@@ -1087,11 +675,30 @@ bool GetScrollOffsets(const base::NativeEvent& native_event,
float* x_offset_ordinal,
float* y_offset_ordinal,
int* finger_count) {
- return CMTEventData::GetInstance()->GetScrollOffsets(
- *native_event,
+ if (!DeviceDataManager::GetInstance()->IsScrollEvent(native_event))
+ return false;
+
+ // Temp values to prevent passing NULLs to DeviceDataManager.
+ float x_offset_, y_offset_;
+ float x_offset_ordinal_, y_offset_ordinal_;
+ int finger_count_;
+ if (!x_offset)
+ x_offset = &x_offset_;
+ if (!y_offset)
+ y_offset = &y_offset_;
+ if (!x_offset_ordinal)
+ x_offset_ordinal = &x_offset_ordinal_;
+ if (!y_offset_ordinal)
+ y_offset_ordinal = &y_offset_ordinal_;
+ if (!finger_count)
+ finger_count = &finger_count_;
+
+ DeviceDataManager::GetInstance()->GetScrollOffsets(
+ native_event,
x_offset, y_offset,
x_offset_ordinal, y_offset_ordinal,
finger_count);
+ return true;
}
bool GetFlingData(const base::NativeEvent& native_event,
@@ -1100,27 +707,55 @@ bool GetFlingData(const base::NativeEvent& native_event,
float* vx_ordinal,
float* vy_ordinal,
bool* is_cancel) {
- return CMTEventData::GetInstance()->GetFlingData(
- *native_event, vx, vy, vx_ordinal, vy_ordinal, is_cancel);
+ if (!DeviceDataManager::GetInstance()->IsFlingEvent(native_event))
+ return false;
+
+ float vx_, vy_;
+ float vx_ordinal_, vy_ordinal_;
+ bool is_cancel_;
+ if (!vx)
+ vx = &vx_;
+ if (!vy)
+ vy = &vy_;
+ if (!vx_ordinal)
+ vx_ordinal = &vx_ordinal_;
+ if (!vy_ordinal)
+ vy_ordinal = &vy_ordinal_;
+ if (!is_cancel)
+ is_cancel = &is_cancel_;
+
+ DeviceDataManager::GetInstance()->GetFlingData(
+ native_event, vx, vy, vx_ordinal, vy_ordinal, is_cancel);
+ return true;
}
bool GetGestureTimes(const base::NativeEvent& native_event,
double* start_time,
double* end_time) {
- return CMTEventData::GetInstance()->GetGestureTimes(
- *native_event, start_time, end_time);
+ if (!DeviceDataManager::GetInstance()->HasGestureTimes(native_event))
+ return false;
+
+ double start_time_, end_time_;
+ if (!start_time)
+ start_time = &start_time_;
+ if (!end_time)
+ end_time = &end_time_;
+
+ DeviceDataManager::GetInstance()->GetGestureTimes(
+ native_event, start_time, end_time);
+ return true;
}
void SetNaturalScroll(bool enabled) {
- CMTEventData::GetInstance()->set_natural_scroll_enabled(enabled);
+ DeviceDataManager::GetInstance()->set_natural_scroll_enabled(enabled);
}
bool IsNaturalScrollEnabled() {
- return CMTEventData::GetInstance()->natural_scroll_enabled();
+ return DeviceDataManager::GetInstance()->natural_scroll_enabled();
}
bool IsTouchpadEvent(const base::NativeEvent& event) {
- return CMTEventData::GetInstance()->IsTouchpadXInputEvent(event);
+ return DeviceDataManager::GetInstance()->IsTouchpadXInputEvent(event);
}
bool IsNoopEvent(const base::NativeEvent& event) {
diff --git a/ui/base/x/valuators.cc b/ui/base/x/valuators.cc
deleted file mode 100644
index da0490e..0000000
--- a/ui/base/x/valuators.cc
+++ /dev/null
@@ -1,184 +0,0 @@
-// 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 "base/memory/singleton.h"
-#include "ui/base/touch/touch_factory_x11.h"
-#include "ui/base/x/device_list_cache_x.h"
-#include "ui/base/x/x11_util.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"
-#define AXIS_LABEL_TOUCH_TIMESTAMP "Touch Timestamp"
-
-// 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_TOUCH_RAW_TIMESTAMP,
- XInternAtom(ui::GetXDisplay(), AXIS_LABEL_TOUCH_TIMESTAMP, 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,
- double* 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,
- double* value) {
- double max_value;
- double 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,
- double* min,
- double* 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();
- XIDeviceList info_list =
- DeviceListCacheX::GetInstance()->GetXI2DeviceList(display);
- TouchFactory* factory = TouchFactory::GetInstance();
-
- for (int i = 0; i < info_list.count; i++) {
- XIDeviceInfo* info = info_list.devices + 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;
- }
- }
- }
-}
-
-} // namespace ui
diff --git a/ui/base/x/valuators.h b/ui/base/x/valuators.h
deleted file mode 100644
index 6a3168a..0000000
--- a/ui/base/x/valuators.h
+++ /dev/null
@@ -1,117 +0,0 @@
-// 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 "base/basictypes.h"
-#include "ui/base/ui_export.h"
-
-template <typename T> struct DefaultSingletonTraits;
-
-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 UI_EXPORT 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.
-
- // Kernel timestamp from touch screen (if available).
- VAL_TOUCH_RAW_TIMESTAMP,
-
- 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, double* 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, double* 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,
- double* min,
- double* 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.
- double valuator_min_[kMaxDeviceNum][VAL_LAST_ENTRY];
- double 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.
- double last_seen_valuator_[kMaxDeviceNum][VAL_LAST_ENTRY];
-
- DISALLOW_COPY_AND_ASSIGN(ValuatorTracker);
-};
-
-} // namespace ui
-
-#endif // UI_BASE_X_VALUATORS_H_
diff --git a/ui/base/x/x11_util.cc b/ui/base/x/x11_util.cc
index 5034ea1..4d06195 100644
--- a/ui/base/x/x11_util.cc
+++ b/ui/base/x/x11_util.cc
@@ -35,7 +35,7 @@
#include "ui/base/events/event_utils.h"
#include "ui/base/keycodes/keyboard_code_conversion_x.h"
#include "ui/base/touch/touch_factory_x11.h"
-#include "ui/base/x/valuators.h"
+#include "ui/base/x/device_data_manager.h"
#include "ui/base/x/x11_util_internal.h"
#include "ui/gfx/point_conversions.h"
#include "ui/gfx/rect.h"
@@ -520,8 +520,8 @@ int CoalescePendingMotionEvents(const XEvent* xev,
if (next_event.type == GenericEvent &&
next_event.xgeneric.evtype == event_type &&
- !ui::GetScrollOffsets(&next_event, NULL, NULL, NULL, NULL, NULL) &&
- !ui::GetFlingData(&next_event, NULL, NULL, NULL, NULL, NULL)) {
+ !ui::DeviceDataManager::GetInstance()->IsCMTGestureEvent(
+ &next_event)) {
XIDeviceEvent* next_xievent =
static_cast<XIDeviceEvent*>(next_event.xcookie.data);
// Confirm that the motion event is targeted at the same window