Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(460)

Side by Side Diff: ui/events/x/device_data_manager.cc

Issue 191223007: Move touch CTM from X into Chrome (Closed) Base URL: http://git.chromium.org/chromium/src.git@master
Patch Set: fix all the unittests Created 6 years, 7 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
1 // Copyright 2013 The Chromium Authors. All rights reserved. 1 // Copyright 2013 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "ui/events/x/device_data_manager.h" 5 #include "ui/events/x/device_data_manager.h"
6 6
7 #include <X11/extensions/XInput.h> 7 #include <X11/extensions/XInput.h>
8 #include <X11/extensions/XInput2.h> 8 #include <X11/extensions/XInput2.h>
9 #include <X11/Xlib.h> 9 #include <X11/Xlib.h>
10 10
11 #include "base/command_line.h"
11 #include "base/logging.h" 12 #include "base/logging.h"
12 #include "base/memory/singleton.h" 13 #include "base/memory/singleton.h"
14 #include "base/strings/string_number_conversions.h"
15 #include "base/strings/string_util.h"
16 #include "base/sys_info.h"
13 #include "ui/events/event_constants.h" 17 #include "ui/events/event_constants.h"
18 #include "ui/events/event_switches.h"
19 #include "ui/events/platform/platform_event_observer.h"
20 #include "ui/events/platform/x11/x11_event_source.h"
14 #include "ui/events/x/device_list_cache_x.h" 21 #include "ui/events/x/device_list_cache_x.h"
15 #include "ui/events/x/touch_factory_x11.h" 22 #include "ui/events/x/touch_factory_x11.h"
23 #include "ui/gfx/display.h"
16 #include "ui/gfx/x/x11_types.h" 24 #include "ui/gfx/x/x11_types.h"
17 25
18 // XIScrollClass was introduced in XI 2.1 so we need to define it here 26 // XIScrollClass was introduced in XI 2.1 so we need to define it here
19 // for backward-compatibility with older versions of XInput. 27 // for backward-compatibility with older versions of XInput.
20 #if !defined(XIScrollClass) 28 #if !defined(XIScrollClass)
21 #define XIScrollClass 3 29 #define XIScrollClass 3
22 #endif 30 #endif
23 31
24 // Multi-touch support was introduced in XI 2.2. Add XI event types here 32 // Multi-touch support was introduced in XI 2.2. Add XI event types here
25 // for backward-compatibility with older versions of XInput. 33 // for backward-compatibility with older versions of XInput.
(...skipping 64 matching lines...) Expand 10 before | Expand all | Expand 10 after
90 98
91 // Constants for checking if a data type lies in the range of CMT/Touch data 99 // Constants for checking if a data type lies in the range of CMT/Touch data
92 // types. 100 // types.
93 const int kCMTDataTypeStart = ui::DeviceDataManager::DT_CMT_SCROLL_X; 101 const int kCMTDataTypeStart = ui::DeviceDataManager::DT_CMT_SCROLL_X;
94 const int kCMTDataTypeEnd = ui::DeviceDataManager::DT_CMT_FINGER_COUNT; 102 const int kCMTDataTypeEnd = ui::DeviceDataManager::DT_CMT_FINGER_COUNT;
95 const int kTouchDataTypeStart = ui::DeviceDataManager::DT_TOUCH_MAJOR; 103 const int kTouchDataTypeStart = ui::DeviceDataManager::DT_TOUCH_MAJOR;
96 const int kTouchDataTypeEnd = ui::DeviceDataManager::DT_TOUCH_RAW_TIMESTAMP; 104 const int kTouchDataTypeEnd = ui::DeviceDataManager::DT_TOUCH_RAW_TIMESTAMP;
97 105
98 namespace ui { 106 namespace ui {
99 107
108 // Accomplishes 2 tasks concerning touch event calibration:
109 // 1. Being a message-pump observer,
110 // routes all the touch events to the X root window,
111 // where they can be calibrated later.
sadrul 2014/05/07 20:00:27 Is this step still necessary?
Yufeng Shen (Slow to review) 2014/05/07 22:02:58 I saw you filed another bug on this. Let's address
spang 2014/05/20 16:38:16 What bug? Please CC if you try to move this code.
Yufeng Shen (Slow to review) 2014/05/20 16:53:42 crbug.com/371060 I think. I am not worrying about
112 // 2. Has the Calibrate method that does the actual bezel calibration,
113 // when invoked from X root window's event dispatcher.
114 class DeviceDataManager::TouchEventCalibrate
115 : public ui::PlatformEventObserver {
116 public:
117 TouchEventCalibrate() : left_(0), right_(0), top_(0), bottom_(0) {
118 if (ui::PlatformEventSource::GetInstance())
119 ui::PlatformEventSource::GetInstance()->AddPlatformEventObserver(this);
120 #if defined(USE_XI2_MT)
121 std::vector<std::string> parts;
122 if (Tokenize(CommandLine::ForCurrentProcess()->GetSwitchValueASCII(
123 switches::kTouchCalibration),
124 ",",
125 &parts) >= 4) {
126 if (!base::StringToInt(parts[0], &left_))
127 DLOG(ERROR) << "Incorrect left border calibration value passed.";
128 if (!base::StringToInt(parts[1], &right_))
129 DLOG(ERROR) << "Incorrect right border calibration value passed.";
130 if (!base::StringToInt(parts[2], &top_))
131 DLOG(ERROR) << "Incorrect top border calibration value passed.";
132 if (!base::StringToInt(parts[3], &bottom_))
133 DLOG(ERROR) << "Incorrect bottom border calibration value passed.";
134 }
135 #endif // defined(USE_XI2_MT)
136 }
137
138 virtual ~TouchEventCalibrate() {
139 if (ui::PlatformEventSource::GetInstance())
140 ui::PlatformEventSource::GetInstance()->RemovePlatformEventObserver(this);
141 }
142
143 // Modify the location of the |event|,
144 // expanding it from |bounds| to (|bounds| + bezels).
145 // Required when touchscreen is bigger than screen (i.e. has bezels),
146 // because we receive events in touchscreen coordinates,
147 // which need to be expanded when converting to screen coordinates,
148 // so that location on bezels will be outside of screen area.
149 void Calibrate(ui::TouchEvent* event, const gfx::Rect& bounds) {
150 #if defined(USE_XI2_MT)
151 int x = event->x();
152 int y = event->y();
153
154 if (!left_ && !right_ && !top_ && !bottom_)
155 return;
156
157 const int resolution_x = bounds.width();
158 const int resolution_y = bounds.height();
159 // The "grace area" (10% in this case) is to make it easier for the user to
160 // navigate to the corner.
161 const double kGraceAreaFraction = 0.1;
162 if (left_ || right_) {
163 // Offset the x position to the real
164 x -= left_;
165 // Check if we are in the grace area of the left side.
166 // Note: We might not want to do this when the gesture is locked?
167 if (x < 0 && x > -left_ * kGraceAreaFraction)
168 x = 0;
169 // Check if we are in the grace area of the right side.
170 // Note: We might not want to do this when the gesture is locked?
171 if (x > resolution_x - left_ &&
172 x < resolution_x - left_ + right_ * kGraceAreaFraction)
173 x = resolution_x - left_;
174 // Scale the screen area back to the full resolution of the screen.
175 x = (x * resolution_x) / (resolution_x - (right_ + left_));
176 }
177 if (top_ || bottom_) {
178 // When there is a top bezel we add our border,
179 y -= top_;
180
181 // Check if we are in the grace area of the top side.
182 // Note: We might not want to do this when the gesture is locked?
183 if (y < 0 && y > -top_ * kGraceAreaFraction)
184 y = 0;
185
186 // Check if we are in the grace area of the bottom side.
187 // Note: We might not want to do this when the gesture is locked?
188 if (y > resolution_y - top_ &&
189 y < resolution_y - top_ + bottom_ * kGraceAreaFraction)
190 y = resolution_y - top_;
191 // Scale the screen area back to the full resolution of the screen.
192 y = (y * resolution_y) / (resolution_y - (bottom_ + top_));
193 }
194
195 // Set the modified coordinate back to the event.
196 if (event->root_location() == event->location()) {
197 // Usually those will be equal,
198 // if not, I am not sure what the correct value should be.
199 event->set_root_location(gfx::Point(x, y));
200 }
201 event->set_location(gfx::Point(x, y));
202 #endif // defined(USE_XI2_MT)
203 }
204
205 private:
206 // ui::PlatformEventObserver:
207 virtual void WillProcessEvent(const ui::PlatformEvent& event) OVERRIDE {
208 #if defined(USE_XI2_MT)
209 if (event->type == GenericEvent &&
210 (event->xgeneric.evtype == XI_TouchBegin ||
211 event->xgeneric.evtype == XI_TouchUpdate ||
212 event->xgeneric.evtype == XI_TouchEnd)) {
213 XIDeviceEvent* xievent = static_cast<XIDeviceEvent*>(event->xcookie.data);
214 LOG(ERROR) << "Raw " << xievent->event_x << " " << xievent->event_y
215 << " " << xievent->root_x << " " << xievent->root_y;
216 xievent->event = xievent->root;
217 xievent->event_x = xievent->root_x;
218 xievent->event_y = xievent->root_y;
219 }
220 #endif // defined(USE_XI2_MT)
221 }
222
223 virtual void DidProcessEvent(const ui::PlatformEvent& event) OVERRIDE {}
224
225 // The difference in screen's native resolution pixels between
226 // the border of the touchscreen and the border of the screen,
227 // aka bezel sizes.
228 int left_;
229 int right_;
230 int top_;
231 int bottom_;
232
233 DISALLOW_COPY_AND_ASSIGN(TouchEventCalibrate);
234 };
235
236 ////////////////////////////////////////////////////////////////////////////////
237 // DeviceDataManager
238
100 bool DeviceDataManager::IsCMTDataType(const int type) { 239 bool DeviceDataManager::IsCMTDataType(const int type) {
101 return (type >= kCMTDataTypeStart) && (type <= kCMTDataTypeEnd); 240 return (type >= kCMTDataTypeStart) && (type <= kCMTDataTypeEnd);
102 } 241 }
103 242
104 bool DeviceDataManager::IsTouchDataType(const int type) { 243 bool DeviceDataManager::IsTouchDataType(const int type) {
105 return (type >= kTouchDataTypeStart) && (type <= kTouchDataTypeEnd); 244 return (type >= kTouchDataTypeStart) && (type <= kTouchDataTypeEnd);
106 } 245 }
107 246
108 DeviceDataManager* DeviceDataManager::GetInstance() { 247 DeviceDataManager* DeviceDataManager::GetInstance() {
109 return Singleton<DeviceDataManager>::get(); 248 return Singleton<DeviceDataManager>::get();
110 } 249 }
111 250
112 DeviceDataManager::DeviceDataManager() 251 DeviceDataManager::DeviceDataManager()
113 : xi_opcode_(-1), 252 : xi_opcode_(-1),
114 atom_cache_(gfx::GetXDisplay(), kCachedAtoms), 253 atom_cache_(gfx::GetXDisplay(), kCachedAtoms),
115 button_map_count_(0) { 254 button_map_count_(0),
255 touch_calibrate_(new TouchEventCalibrate) {
116 CHECK(gfx::GetXDisplay()); 256 CHECK(gfx::GetXDisplay());
117 InitializeXInputInternal(); 257 InitializeXInputInternal();
118 258
119 // Make sure the sizes of enum and kCachedAtoms are aligned. 259 // Make sure the sizes of enum and kCachedAtoms are aligned.
120 CHECK(arraysize(kCachedAtoms) == static_cast<size_t>(DT_LAST_ENTRY) + 1); 260 CHECK(arraysize(kCachedAtoms) == static_cast<size_t>(DT_LAST_ENTRY) + 1);
121 UpdateDeviceList(gfx::GetXDisplay()); 261 UpdateDeviceList(gfx::GetXDisplay());
122 UpdateButtonMap(); 262 UpdateButtonMap();
263 for (int i = 0; i < kMaxDeviceNum; i++)
264 touch_device_to_display_map_[i] = gfx::Display::kInvalidDisplayID;
123 } 265 }
124 266
125 DeviceDataManager::~DeviceDataManager() { 267 DeviceDataManager::~DeviceDataManager() {
126 } 268 }
127 269
128 bool DeviceDataManager::InitializeXInputInternal() { 270 bool DeviceDataManager::InitializeXInputInternal() {
129 // Check if XInput is available on the system. 271 // Check if XInput is available on the system.
130 xi_opcode_ = -1; 272 xi_opcode_ = -1;
131 int opcode, event, error; 273 int opcode, event, error;
132 if (!XQueryExtension( 274 if (!XQueryExtension(
(...skipping 494 matching lines...) Expand 10 before | Expand all | Expand 10 after
627 last_seen_valuator_[deviceid][j].resize(DT_LAST_ENTRY, 0); 769 last_seen_valuator_[deviceid][j].resize(DT_LAST_ENTRY, 0);
628 for (int j = start_valuator; j <= end_valuator; ++j) { 770 for (int j = start_valuator; j <= end_valuator; ++j) {
629 valuator_lookup_[deviceid][j] = valuator_count_[deviceid]; 771 valuator_lookup_[deviceid][j] = valuator_count_[deviceid];
630 data_type_lookup_[deviceid][valuator_count_[deviceid]] = j; 772 data_type_lookup_[deviceid][valuator_count_[deviceid]] = j;
631 valuator_min_[deviceid][j] = min_value; 773 valuator_min_[deviceid][j] = min_value;
632 valuator_max_[deviceid][j] = max_value; 774 valuator_max_[deviceid][j] = max_value;
633 valuator_count_[deviceid]++; 775 valuator_count_[deviceid]++;
634 } 776 }
635 } 777 }
636 778
779 void DeviceDataManager::CalibrateTouchEvent(TouchEvent* event,
780 int touch_device_id,
781 const gfx::Rect& bounds) {
782 #if defined(OS_CHROMEOS) && defined(USE_XI2_MT)
783 int64 touch_display_id = GetDisplayForTouchDevice(touch_device_id);
784 if (base::SysInfo::IsRunningOnChromeOS() &&
785 touch_display_id == gfx::Display::InternalDisplayId()) {
786 touch_calibrate_->Calibrate(event, bounds);
787 }
788 #endif // defined(OS_CHROMEOS) && defined(USE_XI2_MT)
789 }
790
791 void DeviceDataManager::ClearTouchTransformerRecord() {
792 for (int i = 0; i < kMaxDeviceNum; i++) {
793 touch_device_transformer_map_[i] = TouchTransformer();
794 touch_device_to_display_map_[i] = gfx::Display::kInvalidDisplayID;
795 }
796 }
797
798 void DeviceDataManager::UpdateTouchInfoForDisplay(
799 int64 display_id,
800 int touch_device_id,
801 const TouchTransformer& touch_transformer) {
802 if (touch_device_id > 0 && touch_device_id < kMaxDeviceNum) {
sadrul 2014/05/07 20:00:27 Have a separate IsTouchDevideIdValid() and use tha
Yufeng Shen (Slow to review) 2014/05/07 22:02:58 Done.
803 touch_device_to_display_map_[touch_device_id] = display_id;
804 touch_device_transformer_map_[touch_device_id] = touch_transformer;
805 }
806 }
807
808 void DeviceDataManager::ApplyTouchTransformer(int touch_device_id,
809 float* x, float* y) {
810 if (touch_device_id > 0 && touch_device_id < kMaxDeviceNum) {
811 TouchTransformer trans = touch_device_transformer_map_[touch_device_id];
812 *x = *x * trans.x_scale + trans.x_offset;
813 *y = *y * trans.y_scale + trans.y_offset;
814 }
815 }
816
817 int64 DeviceDataManager::GetDisplayForTouchDevice(int touch_device_id) const {
818 if (touch_device_id > 0 && touch_device_id < kMaxDeviceNum)
819 return touch_device_to_display_map_[touch_device_id];
820 return gfx::Display::kInvalidDisplayID;
821 }
822
637 } // namespace ui 823 } // namespace ui
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698