OLD | NEW |
---|---|
1 // Copyright 2014 The Chromium Authors. All rights reserved. | 1 // Copyright 2014 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/ozone/evdev/tablet_event_converter_evdev.h" | 5 #include "ui/events/ozone/evdev/tablet_event_converter_evdev.h" |
6 | 6 |
7 #include <errno.h> | 7 #include <errno.h> |
8 #include <linux/input.h> | 8 #include <linux/input.h> |
9 | 9 |
10 #include "base/message_loop/message_loop.h" | 10 #include "base/message_loop/message_loop.h" |
11 #include "base/time/time.h" | |
11 #include "ui/events/event.h" | 12 #include "ui/events/event.h" |
12 | 13 |
13 namespace ui { | 14 namespace ui { |
14 | 15 |
15 TabletEventConverterEvdev::TabletEventConverterEvdev( | 16 TabletEventConverterEvdev::TabletEventConverterEvdev( |
16 int fd, | 17 int fd, |
17 base::FilePath path, | 18 base::FilePath path, |
18 int id, | 19 int id, |
19 InputDeviceType type, | 20 InputDeviceType type, |
20 EventModifiersEvdev* modifiers, | 21 EventModifiersEvdev* modifiers, |
21 CursorDelegateEvdev* cursor, | 22 CursorDelegateEvdev* cursor, |
22 const EventDeviceInfo& info, | 23 const EventDeviceInfo& info, |
23 const EventDispatchCallback& callback) | 24 const EventDispatchCallback& callback) |
24 : EventConverterEvdev(fd, path, id, type), | 25 : EventConverterEvdev(fd, path, id, type), |
25 cursor_(cursor), | 26 cursor_(cursor), |
26 modifiers_(modifiers), | 27 modifiers_(modifiers), |
27 callback_(callback), | 28 callback_(callback), |
28 stylus_(0), | 29 stylus_(0), |
29 abs_value_dirty_(false) { | 30 abs_value_dirty_(false), |
31 on_screen_stylus_(false) { | |
30 x_abs_min_ = info.GetAbsMinimum(ABS_X); | 32 x_abs_min_ = info.GetAbsMinimum(ABS_X); |
31 x_abs_range_ = info.GetAbsMaximum(ABS_X) - x_abs_min_ + 1; | 33 x_abs_range_ = info.GetAbsMaximum(ABS_X) - x_abs_min_ + 1; |
32 y_abs_min_ = info.GetAbsMinimum(ABS_Y); | 34 y_abs_min_ = info.GetAbsMinimum(ABS_Y); |
33 y_abs_range_ = info.GetAbsMaximum(ABS_Y) - y_abs_min_ + 1; | 35 y_abs_range_ = info.GetAbsMaximum(ABS_Y) - y_abs_min_ + 1; |
36 pressure_min_ = info.GetAbsMinimum(ABS_PRESSURE); | |
37 pressure_range_ = info.GetAbsMaximum(ABS_PRESSURE) - pressure_min_ + 1; | |
38 on_screen_stylus_ = !info.HasProp(INPUT_PROP_POINTER); | |
34 } | 39 } |
35 | 40 |
36 TabletEventConverterEvdev::~TabletEventConverterEvdev() { | 41 TabletEventConverterEvdev::~TabletEventConverterEvdev() { |
37 Stop(); | 42 Stop(); |
38 close(fd_); | 43 close(fd_); |
39 } | 44 } |
40 | 45 |
41 void TabletEventConverterEvdev::OnFileCanReadWithoutBlocking(int fd) { | 46 void TabletEventConverterEvdev::OnFileCanReadWithoutBlocking(int fd) { |
42 input_event inputs[4]; | 47 input_event inputs[4]; |
43 ssize_t read_size = read(fd, inputs, sizeof(inputs)); | 48 ssize_t read_size = read(fd, inputs, sizeof(inputs)); |
(...skipping 18 matching lines...) Expand all Loading... | |
62 for (int i = 0; i < count; ++i) { | 67 for (int i = 0; i < count; ++i) { |
63 const input_event& input = inputs[i]; | 68 const input_event& input = inputs[i]; |
64 switch (input.type) { | 69 switch (input.type) { |
65 case EV_KEY: | 70 case EV_KEY: |
66 ConvertKeyEvent(input); | 71 ConvertKeyEvent(input); |
67 break; | 72 break; |
68 case EV_ABS: | 73 case EV_ABS: |
69 ConvertAbsEvent(input); | 74 ConvertAbsEvent(input); |
70 break; | 75 break; |
71 case EV_SYN: | 76 case EV_SYN: |
72 FlushEvents(); | 77 FlushEvents(input); |
73 break; | 78 break; |
74 } | 79 } |
75 } | 80 } |
76 } | 81 } |
77 | 82 |
78 void TabletEventConverterEvdev::ConvertKeyEvent(const input_event& input) { | 83 void TabletEventConverterEvdev::ConvertKeyEvent(const input_event& input) { |
79 // Only handle other events if we have a stylus in proximity | 84 // Only handle other events if we have a stylus in proximity |
80 if (input.code >= BTN_TOOL_PEN && input.code <= BTN_TOOL_LENS) { | 85 if (input.code >= BTN_TOOL_PEN && input.code <= BTN_TOOL_LENS) { |
81 if (input.value == 1) | 86 if (input.value == 1) |
82 stylus_ = input.code; | 87 stylus_ = input.code; |
83 else if (input.value == 0) | 88 else if (input.value == 0) |
84 stylus_ = 0; | 89 stylus_ = 0; |
85 else | 90 else |
86 LOG(WARNING) << "Unexpected value: " << input.value | 91 LOG(WARNING) << "Unexpected value: " << input.value |
87 << " for code: " << input.code; | 92 << " for code: " << input.code; |
88 } | 93 } |
89 | 94 |
90 if (input.code >= BTN_TOUCH && input.code <= BTN_STYLUS2) { | 95 if (input.code >= BTN_TOUCH && input.code <= BTN_STYLUS2) { |
91 DispatchMouseButton(input); | 96 if (input.code == BTN_TOUCH && on_screen_stylus_) { |
92 return; | 97 DispatchTouch(input); |
98 } else { | |
99 DispatchMouseButton(input); | |
100 } | |
93 } | 101 } |
94 } | 102 } |
95 | 103 |
96 void TabletEventConverterEvdev::ConvertAbsEvent(const input_event& input) { | 104 void TabletEventConverterEvdev::ConvertAbsEvent(const input_event& input) { |
97 if (!cursor_) | 105 if (!cursor_) |
98 return; | 106 return; |
99 | 107 |
100 switch (input.code) { | 108 switch (input.code) { |
101 case ABS_X: | 109 case ABS_X: |
102 x_abs_location_ = input.value; | 110 x_abs_location_ = input.value; |
103 abs_value_dirty_ = true; | 111 abs_value_dirty_ = true; |
104 break; | 112 break; |
105 case ABS_Y: | 113 case ABS_Y: |
106 y_abs_location_ = input.value; | 114 y_abs_location_ = input.value; |
107 abs_value_dirty_ = true; | 115 abs_value_dirty_ = true; |
108 break; | 116 break; |
117 case ABS_PRESSURE: | |
118 pressure_ = input.value; | |
119 break; | |
109 } | 120 } |
110 } | 121 } |
111 | 122 |
112 void TabletEventConverterEvdev::UpdateCursor() { | 123 void TabletEventConverterEvdev::UpdateCursor() { |
113 gfx::Rect display_bounds = cursor_->GetCursorDisplayBounds(); | 124 gfx::Rect display_bounds = cursor_->GetCursorDisplayBounds(); |
114 | 125 |
115 int x = | 126 int x = |
116 ((x_abs_location_ - x_abs_min_) * display_bounds.width()) / x_abs_range_; | 127 ((x_abs_location_ - x_abs_min_) * display_bounds.width()) / x_abs_range_; |
117 int y = | 128 int y = |
118 ((y_abs_location_ - y_abs_min_) * display_bounds.height()) / y_abs_range_; | 129 ((y_abs_location_ - y_abs_min_) * display_bounds.height()) / y_abs_range_; |
119 | 130 |
120 x += display_bounds.x(); | 131 x += display_bounds.x(); |
121 y += display_bounds.y(); | 132 y += display_bounds.y(); |
122 | 133 |
123 cursor_->MoveCursorTo(gfx::PointF(x, y)); | 134 cursor_->MoveCursorTo(gfx::PointF(x, y)); |
124 } | 135 } |
125 | 136 |
137 void TabletEventConverterEvdev::DispatchTouch(const input_event& input) { | |
138 if (abs_value_dirty_) { | |
139 UpdateCursor(); | |
140 abs_value_dirty_ = false; | |
141 } | |
142 | |
143 // Start making motion events touch motion rather than mouse | |
144 emit_touch_ = input.value; | |
145 | |
146 base::TimeDelta delta = base::TimeDelta::FromMicroseconds( | |
147 input.time.tv_sec * 1000000 + input.time.tv_usec); | |
148 scoped_ptr<TouchEvent> touch_event(new TouchEvent( | |
149 input.value ? ET_TOUCH_PRESSED : ET_TOUCH_RELEASED, | |
150 cursor_->GetLocation(), | |
151 /* flags */ 0, | |
152 /* touch_id */ 1, | |
153 /* delta */ delta, | |
154 /* radius_x */ 1.0, | |
155 /* radius_y */ 1.0, | |
156 /* angle */ 0., | |
157 /* force */ (float)(pressure_ - pressure_min_) / pressure_range_)); | |
158 touch_event->set_source_device_id(id_); | |
159 callback_.Run(touch_event.Pass()); | |
160 } | |
161 | |
126 void TabletEventConverterEvdev::DispatchMouseButton(const input_event& input) { | 162 void TabletEventConverterEvdev::DispatchMouseButton(const input_event& input) { |
127 if (!cursor_) | 163 if (!cursor_) |
128 return; | 164 return; |
129 | 165 |
130 unsigned int modifier; | 166 unsigned int modifier; |
131 // These are the same as X11 behaviour | 167 // These are the same as X11 behaviour |
132 if (input.code == BTN_TOUCH) | 168 if (input.code == BTN_TOUCH) |
133 modifier = EVDEV_MODIFIER_LEFT_MOUSE_BUTTON; | 169 modifier = EVDEV_MODIFIER_LEFT_MOUSE_BUTTON; |
134 else if (input.code == BTN_STYLUS2) | 170 else if (input.code == BTN_STYLUS2) |
135 modifier = EVDEV_MODIFIER_RIGHT_MOUSE_BUTTON; | 171 modifier = EVDEV_MODIFIER_RIGHT_MOUSE_BUTTON; |
136 else if (input.code == BTN_STYLUS) | 172 else if (input.code == BTN_STYLUS) |
137 modifier = EVDEV_MODIFIER_MIDDLE_MOUSE_BUTTON; | 173 modifier = EVDEV_MODIFIER_MIDDLE_MOUSE_BUTTON; |
138 else | 174 else |
139 return; | 175 return; |
140 | 176 |
141 if (abs_value_dirty_) { | 177 if (abs_value_dirty_) { |
142 UpdateCursor(); | 178 UpdateCursor(); |
143 abs_value_dirty_ = false; | 179 abs_value_dirty_ = false; |
144 } | 180 } |
145 | 181 |
146 int flag = modifiers_->GetEventFlagFromModifier(modifier); | 182 int flag = modifiers_->GetEventFlagFromModifier(modifier); |
147 modifiers_->UpdateModifier(modifier, input.value); | 183 modifiers_->UpdateModifier(modifier, input.value); |
148 callback_.Run(make_scoped_ptr( | 184 callback_.Run(make_scoped_ptr( |
149 new MouseEvent(input.value ? ET_MOUSE_PRESSED : ET_MOUSE_RELEASED, | 185 new MouseEvent(input.value ? ET_MOUSE_PRESSED : ET_MOUSE_RELEASED, |
150 cursor_->GetLocation(), cursor_->GetLocation(), | 186 cursor_->GetLocation(), cursor_->GetLocation(), |
151 modifiers_->GetModifierFlags() | flag, flag))); | 187 modifiers_->GetModifierFlags() | flag, flag))); |
152 } | 188 } |
153 | 189 |
154 void TabletEventConverterEvdev::FlushEvents() { | 190 void TabletEventConverterEvdev::FlushEvents(const input_event& input) { |
155 if (!cursor_) | 191 if (!cursor_) |
156 return; | 192 return; |
157 | 193 |
158 // Prevent propagation of invalid data on stylus lift off | 194 // Prevent propagation of invalid data on stylus lift off |
159 if (stylus_ == 0) { | 195 if (stylus_ == 0) { |
160 abs_value_dirty_ = false; | 196 abs_value_dirty_ = false; |
161 return; | 197 return; |
162 } | 198 } |
163 | 199 |
164 if (!abs_value_dirty_) | 200 if (!abs_value_dirty_) |
165 return; | 201 return; |
166 | 202 |
167 UpdateCursor(); | 203 UpdateCursor(); |
168 | 204 |
205 if (emit_touch_) { | |
206 base::TimeDelta delta = base::TimeDelta::FromMicroseconds( | |
207 input.time.tv_sec * 1000000 + input.time.tv_usec); | |
208 scoped_ptr<TouchEvent> touch_event(new TouchEvent( | |
209 ET_TOUCH_MOVED, | |
210 cursor_->GetLocation(), | |
211 /* flags */ 0, | |
212 /* touch_id */ 1, | |
Rick Byers
2015/01/19 20:44:20
What if there is both real touchscreen and stylus
| |
213 /* delta */ delta, | |
214 /* radius_x */ 1.0, | |
215 /* radius_y */ 1.0, | |
216 /* angle */ 0., | |
217 /* force */ (float)(pressure_ - pressure_min_) / pressure_range_)); | |
218 touch_event->set_source_device_id(id_); | |
219 callback_.Run(touch_event.Pass()); | |
220 } else { | |
169 callback_.Run(make_scoped_ptr( | 221 callback_.Run(make_scoped_ptr( |
170 new MouseEvent(ui::ET_MOUSE_MOVED, cursor_->GetLocation(), | 222 new MouseEvent(ui::ET_MOUSE_MOVED, cursor_->GetLocation(), |
171 cursor_->GetLocation(), modifiers_->GetModifierFlags(), | 223 cursor_->GetLocation(), modifiers_->GetModifierFlags(), |
172 /* changed_button_flags */ 0))); | 224 /* changed_button_flags */ 0))); |
173 | 225 } |
174 abs_value_dirty_ = false; | 226 abs_value_dirty_ = false; |
175 } | 227 } |
176 | 228 |
177 } // namespace ui | 229 } // namespace ui |
OLD | NEW |