|  | // Copyright 2014 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_EVENTS_X_DEVICE_DATA_MANAGER_X11_H_ | 
|  | #define UI_EVENTS_X_DEVICE_DATA_MANAGER_X11_H_ | 
|  |  | 
|  | // Generically-named #defines from Xlib is conflicting with symbols in GTest. | 
|  | // So many tests .cc file #undef Bool before including device_data_manager.h, | 
|  | // which makes Bool unrecognized in XInput2.h. | 
|  | #ifndef Bool | 
|  | #define Bool int | 
|  | #endif | 
|  |  | 
|  | #include <X11/extensions/XInput2.h> | 
|  |  | 
|  | #include <bitset> | 
|  | #include <map> | 
|  | #include <set> | 
|  | #include <vector> | 
|  |  | 
|  | #include "base/basictypes.h" | 
|  | #include "base/event_types.h" | 
|  | #include "base/memory/scoped_ptr.h" | 
|  | #include "ui/events/device_data_manager.h" | 
|  | #include "ui/events/event_constants.h" | 
|  | #include "ui/events/events_base_export.h" | 
|  | #include "ui/events/keycodes/keyboard_codes.h" | 
|  | #include "ui/gfx/geometry/rect.h" | 
|  | #include "ui/gfx/x/x11_atom_cache.h" | 
|  |  | 
|  | typedef union _XEvent XEvent; | 
|  |  | 
|  | namespace ui { | 
|  |  | 
|  | // CrOS touchpad metrics gesture types | 
|  | enum GestureMetricsType { | 
|  | kGestureMetricsTypeNoisyGround = 0, | 
|  | kGestureMetricsTypeUnknown, | 
|  | }; | 
|  |  | 
|  | // A class that extracts and tracks the input events data. It currently handles | 
|  | // mouse, touchpad and touchscreen devices. | 
|  | class EVENTS_BASE_EXPORT DeviceDataManagerX11 : public 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_METRICS_TYPE,  // Metrics type of the metrics gesture, which are | 
|  | // used to wrap interesting patterns that we would | 
|  | // like to track via the UMA system. | 
|  | DT_CMT_METRICS_DATA1, // Complementary data 1 of the metrics gesture. | 
|  | DT_CMT_METRICS_DATA2, // Complementary data 2 of the metrics gesture. | 
|  | 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. | 
|  |  | 
|  | DT_TOUCH_POSITION_X,  // Touch X position. | 
|  | DT_TOUCH_POSITION_Y,  // Touch Y position. | 
|  |  | 
|  | // 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; | 
|  |  | 
|  | static void CreateInstance(); | 
|  |  | 
|  | // 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 DeviceDataManagerX11 singleton. | 
|  | static DeviceDataManagerX11* GetInstance(); | 
|  |  | 
|  | // Returns if XInput2 is available on the system. | 
|  | bool IsXInput2Available() const; | 
|  |  | 
|  | // Updates the list of devices. | 
|  | void UpdateDeviceList(Display* display); | 
|  |  | 
|  | // For multitouch events we use slot number to distinguish touches from | 
|  | // different fingers. This function returns true if the associated slot | 
|  | // for |xiev| can be found and it is saved in |slot|, returns false if | 
|  | // no slot can be found. | 
|  | bool GetSlotNumber(const XIDeviceEvent* xiev, int* slot); | 
|  |  | 
|  | // 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 is an XI input event in the strict sense | 
|  | // (i.e. XIDeviceEvent). This rules out things like hierarchy changes, | 
|  | /// device changes, property changes and so on. | 
|  | bool IsXIDeviceEvent(const base::NativeEvent& native_event) const; | 
|  |  | 
|  | // 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; | 
|  | bool IsCMTMetricsEvent(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 data from a CrOS metrics gesture event. User must first verify | 
|  | // the event type with IsCMTMetricsEvent. Pointers shouldn't be NULL. | 
|  | void GetMetricsData(const base::NativeEvent& native_event, | 
|  | GestureMetricsType* type, | 
|  | float* data1, | 
|  | float* data2); | 
|  |  | 
|  | // Returns the mapped button. | 
|  | int GetMappedButton(int button); | 
|  |  | 
|  | // Updates button mapping. This is usually called when a MappingNotify event | 
|  | // is received. | 
|  | void UpdateButtonMap(); | 
|  |  | 
|  | // 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); | 
|  |  | 
|  | // Sets up relevant valuator informations for device ids in the device lists. | 
|  | // This function is only for test purpose. It does not query the X server for | 
|  | // the actual device info, but rather inits the relevant valuator structures | 
|  | // to have safe default values for testing. | 
|  | void SetDeviceListForTest(const std::vector<unsigned int>& touchscreen, | 
|  | const std::vector<unsigned int>& cmt_devices); | 
|  |  | 
|  | void SetValuatorDataForTest(XIDeviceEvent* xievent, | 
|  | DataType type, | 
|  | double value); | 
|  |  | 
|  | bool TouchEventNeedsCalibrate(int touch_device_id) const; | 
|  |  | 
|  | // Sets the keys which are still allowed on a disabled keyboard device. | 
|  | void SetDisabledKeyboardAllowedKeys( | 
|  | scoped_ptr<std::set<KeyboardCode> > excepted_keys); | 
|  |  | 
|  | // Disables and enables events from devices by device id. | 
|  | void DisableDevice(unsigned int deviceid); | 
|  | void EnableDevice(unsigned int deviceid); | 
|  |  | 
|  | // Returns true if |native_event| should be blocked. | 
|  | bool IsEventBlocked(const base::NativeEvent& native_event); | 
|  |  | 
|  | private: | 
|  | DeviceDataManagerX11(); | 
|  | virtual ~DeviceDataManagerX11(); | 
|  |  | 
|  | // Initialize the XInput related system information. | 
|  | bool InitializeXInputInternal(); | 
|  |  | 
|  | // Check if an XI event contains data of the specified type. | 
|  | bool HasEventData(const XIDeviceEvent* xiev, const DataType type) const; | 
|  |  | 
|  | void InitializeValuatorsForTest(int deviceid, | 
|  | int start_valuator, | 
|  | int end_valuator, | 
|  | double min_value, | 
|  | double max_value); | 
|  |  | 
|  | static const int kMaxXIEventType = XI_LASTEVENT + 1; | 
|  | static const int kMaxSlotNum = 10; | 
|  |  | 
|  | // Major opcode for the XInput extension. Used to identify XInput events. | 
|  | int xi_opcode_; | 
|  |  | 
|  | // A quick lookup table for determining if the XI event is an XIDeviceEvent. | 
|  | std::bitset<kMaxXIEventType> xi_device_event_types_; | 
|  |  | 
|  | // A quick lookup table for determining if events from the pointer device | 
|  | // should be processed. | 
|  | std::bitset<kMaxDeviceNum> cmt_devices_; | 
|  | std::bitset<kMaxDeviceNum> touchpads_; | 
|  |  | 
|  | // A quick lookup table for determining if events from the XI device | 
|  | // should be blocked. | 
|  | std::bitset<kMaxDeviceNum> blocked_devices_; | 
|  |  | 
|  | // The set of keys allowed while the keyboard is blocked. | 
|  | scoped_ptr<std::set<KeyboardCode> > blocked_keyboard_allowed_keys_; | 
|  |  | 
|  | // 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 specified slot of a device. Defaults to 0 if the valuator for that slot | 
|  | // 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][kMaxSlotNum]; | 
|  |  | 
|  | // X11 atoms cache. | 
|  | X11AtomCache atom_cache_; | 
|  |  | 
|  | unsigned char button_map_[256]; | 
|  | int button_map_count_; | 
|  |  | 
|  | DISALLOW_COPY_AND_ASSIGN(DeviceDataManagerX11); | 
|  | }; | 
|  |  | 
|  | }  // namespace ui | 
|  |  | 
|  | #endif  // UI_EVENTS_X_DEVICE_DATA_MANAGER_X11_H_ |