1// Copyright (c) 2012 The Chromium Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5#ifndef UI_EVENTS_X_TOUCH_FACTORY_X11_H_
6#define UI_EVENTS_X_TOUCH_FACTORY_X11_H_
7
8#include <bitset>
9#include <map>
10#include <set>
11#include <utility>
12#include <vector>
13
14#include "base/timer/timer.h"
15#include "ui/events/events_base_export.h"
16#include "ui/gfx/sequential_id_generator.h"
17
18template <typename T> struct DefaultSingletonTraits;
19
20typedef unsigned long Cursor;
21typedef unsigned long Window;
22typedef struct _XDisplay Display;
23typedef union _XEvent XEvent;
24
25namespace ui {
26
27// Functions related to determining touch devices.
28class EVENTS_BASE_EXPORT TouchFactory {
29 private:
30  TouchFactory();
31  ~TouchFactory();
32
33 public:
34  // Returns the TouchFactory singleton.
35  static TouchFactory* GetInstance();
36
37  // Sets the touch devices from the command line.
38  static void SetTouchDeviceListFromCommandLine();
39
40  // Updates the list of devices.
41  void UpdateDeviceList(Display* display);
42
43  // Checks whether an XI2 event should be processed or not (i.e. if the event
44  // originated from a device we are interested in).
45  bool ShouldProcessXI2Event(XEvent* xevent);
46
47  // Setup an X Window for XInput2 events.
48  void SetupXI2ForXWindow(::Window xid);
49
50  // Keeps a list of touch devices so that it is possible to determine if a
51  // pointer event is a touch-event or a mouse-event. The list is reset each
52  // time this is called.
53  void SetTouchDeviceList(const std::vector<unsigned int>& devices);
54
55  // Is the device a touch-device?
56  bool IsTouchDevice(unsigned int deviceid) const;
57
58  // Is the device a real multi-touch-device? (see doc. for |touch_device_list_|
59  // below for more explanation.)
60  bool IsMultiTouchDevice(unsigned int deviceid) const;
61
62  // Tries to find an existing slot ID mapping to tracking ID. Returns true
63  // if the slot is found and it is saved in |slot|, false if no such slot
64  // can be found.
65  bool QuerySlotForTrackingID(uint32 tracking_id, int* slot);
66
67  // Tries to find an existing slot ID mapping to tracking ID. If there
68  // isn't one already, allocates a new slot ID and sets up the mapping.
69  int GetSlotForTrackingID(uint32 tracking_id);
70
71  // Increases the number of times |ReleaseSlotForTrackingID| needs to be called
72  // on a given tracking id before it will actually be released.
73  void AcquireSlotForTrackingID(uint32 tracking_id);
74
75  // Releases the slot ID mapping to tracking ID.
76  void ReleaseSlotForTrackingID(uint32 tracking_id);
77
78  // Whether any touch device is currently present and enabled.
79  bool IsTouchDevicePresent();
80
81  // Pairs of <vendor id, product id> of external touch screens.
82  const std::set<std::pair<int, int> >& GetTouchscreenIds() const {
83    return touchscreen_ids_;
84  }
85
86  // Return maximum simultaneous touch points supported by device.
87  int GetMaxTouchPoints() const;
88
89  // Resets the TouchFactory singleton.
90  void ResetForTest();
91
92  // Sets up the device id in the list |devices| as multi-touch capable
93  // devices and enables touch events processing. This function is only
94  // for test purpose, and it does not query from X server.
95  void SetTouchDeviceForTest(const std::vector<unsigned int>& devices);
96
97  // Sets up the device id in the list |devices| as pointer devices.
98  // This function is only for test purpose, and it does not query from
99  // X server.
100  void SetPointerDeviceForTest(const std::vector<unsigned int>& devices);
101
102 private:
103  // Requirement for Singleton
104  friend struct DefaultSingletonTraits<TouchFactory>;
105
106  void CacheTouchscreenIds(Display* display, int id);
107
108  // NOTE: To keep track of touch devices, we currently maintain a lookup table
109  // to quickly decide if a device is a touch device or not. We also maintain a
110  // list of the touch devices. Ideally, there will be only one touch device,
111  // and instead of having the lookup table and the list, there will be a single
112  // identifier for the touch device. This can be completed after enough testing
113  // on real touch devices.
114
115  static const int kMaxDeviceNum = 128;
116
117  // A quick lookup table for determining if events from the pointer device
118  // should be processed.
119  std::bitset<kMaxDeviceNum> pointer_device_lookup_;
120
121  // A quick lookup table for determining if a device is a touch device.
122  std::bitset<kMaxDeviceNum> touch_device_lookup_;
123
124  // Indicates whether a touch device is currently available or not.
125  bool touch_device_available_;
126
127  // Indicates whether touch events are explicitly disabled.
128  bool touch_events_disabled_;
129
130  // The list of touch devices. For testing/debugging purposes, a single-pointer
131  // device (mouse or touch screen without sufficient X/driver support for MT)
132  // can sometimes be treated as a touch device. The key in the map represents
133  // the device id, and the value represents if the device is multi-touch
134  // capable.
135  std::map<int, bool> touch_device_list_;
136
137  // Touch screen <vid, pid>s.
138  std::set<std::pair<int, int> > touchscreen_ids_;
139
140  // Maps from a tracking id to the number of times |ReleaseSlotForTrackingID|
141  // must be called before the tracking id is released.
142  std::map<uint32, int> tracking_id_refcounts_;
143
144  // Maximum simultaneous touch points supported by device. In the case of
145  // devices with multiple digitizers (e.g. multiple touchscreens), the value
146  // is the maximum of the set of maximum supported contacts by each individual
147  // digitizer.
148  int max_touch_points_;
149
150  // Device ID of the virtual core keyboard.
151  int virtual_core_keyboard_device_;
152
153  SequentialIDGenerator id_generator_;
154
155  DISALLOW_COPY_AND_ASSIGN(TouchFactory);
156};
157
158}  // namespace ui
159
160#endif  // UI_EVENTS_X_TOUCH_FACTORY_X11_H_
161