OLD | NEW |
1 // Copyright 2015 The Chromium Authors. All rights reserved. | 1 // Copyright 2015 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 "components/arc/input/arc_input_bridge_impl.h" | 5 #include "components/arc/input/arc_input_bridge.h" |
6 | 6 |
7 #include <linux/input.h> | 7 #include <linux/input.h> |
8 #include <fcntl.h> | 8 #include <fcntl.h> |
9 #include <stddef.h> | 9 #include <stddef.h> |
10 | 10 |
11 #include <string> | 11 #include <string> |
12 | 12 |
13 #include "base/logging.h" | 13 #include "base/logging.h" |
14 #include "base/posix/eintr_wrapper.h" | 14 #include "base/posix/eintr_wrapper.h" |
15 #include "base/thread_task_runner_handle.h" | 15 #include "base/thread_task_runner_handle.h" |
(...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
69 {ui::EF_MIDDLE_MOUSE_BUTTON, BTN_MIDDLE}, | 69 {ui::EF_MIDDLE_MOUSE_BUTTON, BTN_MIDDLE}, |
70 }; | 70 }; |
71 | 71 |
72 // Offset between evdev key codes and chrome native key codes | 72 // Offset between evdev key codes and chrome native key codes |
73 const int kXkbKeycodeOffset = 8; | 73 const int kXkbKeycodeOffset = 8; |
74 | 74 |
75 } // namespace | 75 } // namespace |
76 | 76 |
77 namespace arc { | 77 namespace arc { |
78 | 78 |
79 ArcInputBridgeImpl::ArcInputBridgeImpl(ArcBridgeService* arc_bridge_service) | 79 ArcInputBridge::ArcInputBridge(ArcBridgeService* arc_bridge) |
80 : arc_bridge_service_(arc_bridge_service), | 80 : arc_bridge_service_(arc_bridge), |
81 offset_x_acc_(0.5f), | 81 offset_x_acc_(0.5f), |
82 offset_y_acc_(0.5f), | 82 offset_y_acc_(0.5f), |
83 current_slot_(-1), | 83 current_slot_(-1), |
84 current_slot_tracking_ids_(kMaxSlots, kEmptySlot), | 84 current_slot_tracking_ids_(kMaxSlots, kEmptySlot), |
85 origin_task_runner_(base::ThreadTaskRunnerHandle::Get()), | 85 origin_task_runner_(base::ThreadTaskRunnerHandle::Get()), |
86 weak_factory_(this) { | 86 weak_factory_(this) { |
87 arc_bridge_service->AddObserver(this); | 87 DCHECK(arc_bridge_service_); |
88 if (arc_bridge_service->input_instance()) | 88 arc_bridge_service_->AddObserver(this); |
| 89 |
| 90 // If InputInstance was ready before we AddObserver(), we won't get |
| 91 // OnInputInstanceReady events. For such case, we have to call it |
| 92 // explicitly. |
| 93 if (arc_bridge_service_->input_instance()) |
89 OnInputInstanceReady(); | 94 OnInputInstanceReady(); |
90 | 95 |
91 aura::Env* env = aura::Env::GetInstanceDontCreate(); | 96 aura::Env* env = aura::Env::GetInstanceDontCreate(); |
92 if (env) | 97 if (env) |
93 env->AddObserver(this); | 98 env->AddObserver(this); |
94 } | 99 } |
95 | 100 |
96 ArcInputBridgeImpl::~ArcInputBridgeImpl() { | 101 ArcInputBridge::~ArcInputBridge() { |
97 DCHECK(origin_task_runner_->RunsTasksOnCurrentThread()); | 102 DCHECK(origin_task_runner_->RunsTasksOnCurrentThread()); |
98 arc_bridge_service_->RemoveObserver(this); | 103 arc_bridge_service_->RemoveObserver(this); |
99 | 104 |
100 aura::Env* env = aura::Env::GetInstanceDontCreate(); | 105 aura::Env* env = aura::Env::GetInstanceDontCreate(); |
101 if (env) | 106 if (env) |
102 env->RemoveObserver(this); | 107 env->RemoveObserver(this); |
103 | 108 |
104 for (aura::Window* window : arc_windows_.windows()) { | 109 for (aura::Window* window : arc_windows_.windows()) { |
105 window->RemovePreTargetHandler(this); | 110 window->RemovePreTargetHandler(this); |
106 } | 111 } |
107 } | 112 } |
108 | 113 |
109 void ArcInputBridgeImpl::OnInputInstanceReady() { | 114 void ArcInputBridge::OnInputInstanceReady() { |
110 DCHECK(origin_task_runner_->RunsTasksOnCurrentThread()); | 115 DCHECK(origin_task_runner_->RunsTasksOnCurrentThread()); |
111 | 116 |
112 keyboard_fd_ = CreateBridgeInputDevice("ChromeOS Keyboard", "keyboard"); | 117 keyboard_fd_ = CreateBridgeInputDevice("ChromeOS Keyboard", "keyboard"); |
113 mouse_fd_ = CreateBridgeInputDevice("ChromeOS Mouse", "mouse"); | 118 mouse_fd_ = CreateBridgeInputDevice("ChromeOS Mouse", "mouse"); |
114 touchscreen_fd_ = | 119 touchscreen_fd_ = |
115 CreateBridgeInputDevice("ChromeOS Touchscreen", "touchscreen"); | 120 CreateBridgeInputDevice("ChromeOS Touchscreen", "touchscreen"); |
116 } | 121 } |
117 | 122 |
118 // Translates and sends a ui::Event to the appropriate bridge device of the | 123 // Translates and sends a ui::Event to the appropriate bridge device of the |
119 // ARC instance. If the devices have not yet been initialized, the event | 124 // ARC instance. If the devices have not yet been initialized, the event |
120 // will be ignored. | 125 // will be ignored. |
121 void ArcInputBridgeImpl::OnEvent(ui::Event* event) { | 126 void ArcInputBridge::OnEvent(ui::Event* event) { |
122 DCHECK(origin_task_runner_->RunsTasksOnCurrentThread()); | 127 DCHECK(origin_task_runner_->RunsTasksOnCurrentThread()); |
123 if (event->IsKeyEvent()) { | 128 if (event->IsKeyEvent()) { |
124 SendKeyEvent(static_cast<ui::KeyEvent*>(event)); | 129 SendKeyEvent(static_cast<ui::KeyEvent*>(event)); |
125 } else if (event->IsMouseEvent() || event->IsScrollEvent()) { | 130 } else if (event->IsMouseEvent() || event->IsScrollEvent()) { |
126 SendMouseEvent(static_cast<ui::MouseEvent*>(event)); | 131 SendMouseEvent(static_cast<ui::MouseEvent*>(event)); |
127 } else if (event->IsTouchEvent()) { | 132 } else if (event->IsTouchEvent()) { |
128 SendTouchEvent(static_cast<ui::TouchEvent*>(event)); | 133 SendTouchEvent(static_cast<ui::TouchEvent*>(event)); |
129 } | 134 } |
130 } | 135 } |
131 | 136 |
132 // Attaches the input bridge to the window if it is marked as an ARC window. | 137 // Attaches the input bridge to the window if it is marked as an ARC window. |
133 void ArcInputBridgeImpl::OnWindowInitialized(aura::Window* new_window) { | 138 void ArcInputBridge::OnWindowInitialized(aura::Window* new_window) { |
134 if (new_window->name() == "ExoSurface") { | 139 if (new_window->name() == "ExoSurface") { |
135 arc_windows_.Add(new_window); | 140 arc_windows_.Add(new_window); |
136 new_window->AddPreTargetHandler(this); | 141 new_window->AddPreTargetHandler(this); |
137 } | 142 } |
138 } | 143 } |
139 | 144 |
140 void ArcInputBridgeImpl::SendKeyEvent(ui::KeyEvent* event) { | 145 void ArcInputBridge::SendKeyEvent(ui::KeyEvent* event) { |
141 if (keyboard_fd_.get() < 0) { | 146 if (keyboard_fd_.get() < 0) { |
142 VLOG(2) << "No keyboard bridge device available."; | 147 VLOG(2) << "No keyboard bridge device available."; |
143 return; | 148 return; |
144 } | 149 } |
145 | 150 |
146 uint16_t evdev_code = DomCodeToEvdevCode(event->code()); | 151 uint16_t evdev_code = DomCodeToEvdevCode(event->code()); |
147 int evdev_value = 0; | 152 int evdev_value = 0; |
148 if (event->type() == ui::ET_KEY_PRESSED) { | 153 if (event->type() == ui::ET_KEY_PRESSED) { |
149 if (event->flags() & ui::EF_IS_REPEAT) { | 154 if (event->flags() & ui::EF_IS_REPEAT) { |
150 evdev_value = kKeyRepeated; | 155 evdev_value = kKeyRepeated; |
151 } else { | 156 } else { |
152 evdev_value = kKeyPressed; | 157 evdev_value = kKeyPressed; |
153 } | 158 } |
154 } else if (event->type() == ui::ET_KEY_RELEASED) { | 159 } else if (event->type() == ui::ET_KEY_RELEASED) { |
155 evdev_value = kKeyReleased; | 160 evdev_value = kKeyReleased; |
156 } else { | 161 } else { |
157 NOTREACHED() << "Key should be either PRESSED or RELEASED."; | 162 NOTREACHED() << "Key should be either PRESSED or RELEASED."; |
158 } | 163 } |
159 | 164 |
160 base::TimeDelta time_stamp = event->time_stamp(); | 165 base::TimeDelta time_stamp = event->time_stamp(); |
161 SendKernelEvent(keyboard_fd_, time_stamp, EV_KEY, evdev_code, evdev_value); | 166 SendKernelEvent(keyboard_fd_, time_stamp, EV_KEY, evdev_code, evdev_value); |
162 SendSynReport(keyboard_fd_, time_stamp); | 167 SendSynReport(keyboard_fd_, time_stamp); |
163 } | 168 } |
164 | 169 |
165 void ArcInputBridgeImpl::SendTouchEvent(ui::TouchEvent* event) { | 170 void ArcInputBridge::SendTouchEvent(ui::TouchEvent* event) { |
166 if (touchscreen_fd_.get() < 0) { | 171 if (touchscreen_fd_.get() < 0) { |
167 VLOG(2) << "No touchscreen bridge device available."; | 172 VLOG(2) << "No touchscreen bridge device available."; |
168 return; | 173 return; |
169 } | 174 } |
170 | 175 |
171 ui::PointerDetails details = event->pointer_details(); | 176 ui::PointerDetails details = event->pointer_details(); |
172 base::TimeDelta time_stamp = event->time_stamp(); | 177 base::TimeDelta time_stamp = event->time_stamp(); |
173 | 178 |
174 // find or assing a slot for this tracking id | 179 // find or assing a slot for this tracking id |
175 int slot_id = AcquireTouchSlot(event); | 180 int slot_id = AcquireTouchSlot(event); |
(...skipping 28 matching lines...) Expand all Loading... |
204 SendKernelEvent(touchscreen_fd_, time_stamp, EV_ABS, ABS_MT_TOUCH_MAJOR, | 209 SendKernelEvent(touchscreen_fd_, time_stamp, EV_ABS, ABS_MT_TOUCH_MAJOR, |
205 details.radius_x()); | 210 details.radius_x()); |
206 SendKernelEvent(touchscreen_fd_, time_stamp, EV_ABS, ABS_MT_TOUCH_MINOR, | 211 SendKernelEvent(touchscreen_fd_, time_stamp, EV_ABS, ABS_MT_TOUCH_MINOR, |
207 details.radius_y()); | 212 details.radius_y()); |
208 SendKernelEvent(touchscreen_fd_, time_stamp, EV_ABS, ABS_MT_PRESSURE, | 213 SendKernelEvent(touchscreen_fd_, time_stamp, EV_ABS, ABS_MT_PRESSURE, |
209 details.force() * kMaxPressure); | 214 details.force() * kMaxPressure); |
210 } | 215 } |
211 SendSynReport(touchscreen_fd_, time_stamp); | 216 SendSynReport(touchscreen_fd_, time_stamp); |
212 } | 217 } |
213 | 218 |
214 void ArcInputBridgeImpl::SendMouseEvent(ui::MouseEvent* event) { | 219 void ArcInputBridge::SendMouseEvent(ui::MouseEvent* event) { |
215 if (mouse_fd_.get() < 0) { | 220 if (mouse_fd_.get() < 0) { |
216 VLOG(2) << "No mouse bridge device available."; | 221 VLOG(2) << "No mouse bridge device available."; |
217 return; | 222 return; |
218 } | 223 } |
219 | 224 |
220 base::TimeDelta time_stamp = event->time_stamp(); | 225 base::TimeDelta time_stamp = event->time_stamp(); |
221 | 226 |
222 // update location | 227 // update location |
223 if (event->type() == ui::ET_MOUSE_MOVED || | 228 if (event->type() == ui::ET_MOUSE_MOVED || |
224 event->type() == ui::ET_MOUSE_DRAGGED) { | 229 event->type() == ui::ET_MOUSE_DRAGGED) { |
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
256 int hwheel = floor(offset_x_acc_); | 261 int hwheel = floor(offset_x_acc_); |
257 if (hwheel != 0) { | 262 if (hwheel != 0) { |
258 SendKernelEvent(mouse_fd_, time_stamp, EV_REL, REL_HWHEEL, hwheel); | 263 SendKernelEvent(mouse_fd_, time_stamp, EV_REL, REL_HWHEEL, hwheel); |
259 offset_x_acc_ -= static_cast<float>(hwheel); | 264 offset_x_acc_ -= static_cast<float>(hwheel); |
260 } | 265 } |
261 } | 266 } |
262 | 267 |
263 SendSynReport(mouse_fd_, time_stamp); | 268 SendSynReport(mouse_fd_, time_stamp); |
264 } | 269 } |
265 | 270 |
266 void ArcInputBridgeImpl::SendKernelEvent(const base::ScopedFD& fd, | 271 void ArcInputBridge::SendKernelEvent(const base::ScopedFD& fd, |
267 base::TimeDelta time_stamp, | 272 base::TimeDelta time_stamp, |
268 uint16_t type, | 273 uint16_t type, |
269 uint16_t code, | 274 uint16_t code, |
270 int value) { | 275 int value) { |
271 DCHECK(fd.is_valid()); | 276 DCHECK(fd.is_valid()); |
272 | 277 |
273 struct input_event32 event; | 278 struct input_event32 event; |
274 event.time.tv_sec = time_stamp.InSeconds(); | 279 event.time.tv_sec = time_stamp.InSeconds(); |
275 base::TimeDelta remainder = | 280 base::TimeDelta remainder = |
276 time_stamp - base::TimeDelta::FromSeconds(event.time.tv_sec); | 281 time_stamp - base::TimeDelta::FromSeconds(event.time.tv_sec); |
277 event.time.tv_usec = remainder.InMicroseconds(); | 282 event.time.tv_usec = remainder.InMicroseconds(); |
278 event.type = type; | 283 event.type = type; |
279 event.code = code; | 284 event.code = code; |
280 event.value = value; | 285 event.value = value; |
281 | 286 |
282 // Write event to file descriptor | 287 // Write event to file descriptor |
283 size_t num_written = write(fd.get(), reinterpret_cast<void*>(&event), | 288 size_t num_written = write(fd.get(), reinterpret_cast<void*>(&event), |
284 sizeof(struct input_event32)); | 289 sizeof(struct input_event32)); |
285 DCHECK_EQ(num_written, sizeof(struct input_event32)); | 290 DCHECK_EQ(num_written, sizeof(struct input_event32)); |
286 } | 291 } |
287 | 292 |
288 void ArcInputBridgeImpl::SendSynReport(const base::ScopedFD& fd, | 293 void ArcInputBridge::SendSynReport(const base::ScopedFD& fd, |
289 base::TimeDelta time) { | 294 base::TimeDelta time) { |
290 DCHECK(origin_task_runner_->RunsTasksOnCurrentThread()); | 295 DCHECK(origin_task_runner_->RunsTasksOnCurrentThread()); |
291 | 296 |
292 SendKernelEvent(fd, time, EV_SYN, SYN_REPORT, 0); | 297 SendKernelEvent(fd, time, EV_SYN, SYN_REPORT, 0); |
293 } | 298 } |
294 | 299 |
295 int ArcInputBridgeImpl::AcquireTouchSlot(ui::TouchEvent* event) { | 300 int ArcInputBridge::AcquireTouchSlot(ui::TouchEvent* event) { |
296 int slot_id; | 301 int slot_id; |
297 if (event->type() == ui::ET_TOUCH_PRESSED) { | 302 if (event->type() == ui::ET_TOUCH_PRESSED) { |
298 slot_id = FindTouchSlot(kEmptySlot); | 303 slot_id = FindTouchSlot(kEmptySlot); |
299 } else { | 304 } else { |
300 slot_id = FindTouchSlot(event->touch_id()); | 305 slot_id = FindTouchSlot(event->touch_id()); |
301 } | 306 } |
302 if (slot_id < 0) { | 307 if (slot_id < 0) { |
303 return -1; | 308 return -1; |
304 } | 309 } |
305 | 310 |
306 if (event->type() == ui::ET_TOUCH_RELEASED) { | 311 if (event->type() == ui::ET_TOUCH_RELEASED) { |
307 current_slot_tracking_ids_[slot_id] = kEmptySlot; | 312 current_slot_tracking_ids_[slot_id] = kEmptySlot; |
308 } else if (event->type() == ui::ET_TOUCH_PRESSED) { | 313 } else if (event->type() == ui::ET_TOUCH_PRESSED) { |
309 current_slot_tracking_ids_[slot_id] = event->touch_id(); | 314 current_slot_tracking_ids_[slot_id] = event->touch_id(); |
310 } | 315 } |
311 return slot_id; | 316 return slot_id; |
312 } | 317 } |
313 | 318 |
314 int ArcInputBridgeImpl::FindTouchSlot(int tracking_id) { | 319 int ArcInputBridge::FindTouchSlot(int tracking_id) { |
315 for (int i = 0; i < kMaxSlots; ++i) { | 320 for (int i = 0; i < kMaxSlots; ++i) { |
316 if (current_slot_tracking_ids_[i] == tracking_id) { | 321 if (current_slot_tracking_ids_[i] == tracking_id) { |
317 return i; | 322 return i; |
318 } | 323 } |
319 } | 324 } |
320 return -1; | 325 return -1; |
321 } | 326 } |
322 | 327 |
323 uint16_t ArcInputBridgeImpl::DomCodeToEvdevCode(ui::DomCode dom_code) { | 328 uint16_t ArcInputBridge::DomCodeToEvdevCode(ui::DomCode dom_code) { |
324 int native_code = ui::KeycodeConverter::DomCodeToNativeKeycode(dom_code); | 329 int native_code = ui::KeycodeConverter::DomCodeToNativeKeycode(dom_code); |
325 if (native_code == ui::KeycodeConverter::InvalidNativeKeycode()) | 330 if (native_code == ui::KeycodeConverter::InvalidNativeKeycode()) |
326 return KEY_RESERVED; | 331 return KEY_RESERVED; |
327 | 332 |
328 return native_code - kXkbKeycodeOffset; | 333 return native_code - kXkbKeycodeOffset; |
329 } | 334 } |
330 | 335 |
331 base::ScopedFD ArcInputBridgeImpl::CreateBridgeInputDevice( | 336 base::ScopedFD ArcInputBridge::CreateBridgeInputDevice( |
332 const std::string& name, | 337 const std::string& name, |
333 const std::string& device_type) { | 338 const std::string& device_type) { |
334 if (!arc_bridge_service_) { | |
335 VLOG(1) << "ArcBridgeService disappeared."; | |
336 return base::ScopedFD(); | |
337 } | |
338 | |
339 // Create file descriptor pair for communication | 339 // Create file descriptor pair for communication |
340 int fd[2]; | 340 int fd[2]; |
341 int res = HANDLE_EINTR(pipe(fd)); | 341 int res = HANDLE_EINTR(pipe(fd)); |
342 if (res < 0) { | 342 if (res < 0) { |
343 VPLOG(1) << "Cannot create pipe"; | 343 VPLOG(1) << "Cannot create pipe"; |
344 return base::ScopedFD(); | 344 return base::ScopedFD(); |
345 } | 345 } |
346 base::ScopedFD read_fd(fd[0]); | 346 base::ScopedFD read_fd(fd[0]); |
347 base::ScopedFD write_fd(fd[1]); | 347 base::ScopedFD write_fd(fd[1]); |
348 | 348 |
(...skipping 23 matching lines...) Expand all Loading... |
372 } | 372 } |
373 | 373 |
374 res = HANDLE_EINTR(fcntl(write_fd.get(), F_SETFL, flags | O_NONBLOCK)); | 374 res = HANDLE_EINTR(fcntl(write_fd.get(), F_SETFL, flags | O_NONBLOCK)); |
375 if (res < 0) { | 375 if (res < 0) { |
376 VPLOG(1) << "Cannot set file descriptor flags"; | 376 VPLOG(1) << "Cannot set file descriptor flags"; |
377 return base::ScopedFD(); | 377 return base::ScopedFD(); |
378 } | 378 } |
379 return write_fd; | 379 return write_fd; |
380 } | 380 } |
381 | 381 |
382 scoped_ptr<ArcInputBridge> ArcInputBridge::Create( | |
383 ArcBridgeService* arc_bridge_service) { | |
384 return make_scoped_ptr(new ArcInputBridgeImpl(arc_bridge_service)); | |
385 } | |
386 | |
387 } // namespace arc | 382 } // namespace arc |
OLD | NEW |