OLD | NEW |
(Empty) | |
| 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 |
| 3 // found in the LICENSE file. |
| 4 |
| 5 #include "ui/events/ozone/evdev/tablet_event_converter_evdev.h" |
| 6 |
| 7 #include <errno.h> |
| 8 #include <linux/input.h> |
| 9 |
| 10 #include "base/message_loop/message_loop.h" |
| 11 #include "base/trace_event/trace_event.h" |
| 12 #include "ui/events/event.h" |
| 13 #include "ui/events/ozone/evdev/device_event_dispatcher_evdev.h" |
| 14 |
| 15 namespace ui { |
| 16 |
| 17 TabletEventConverterEvdev::TabletEventConverterEvdev( |
| 18 int fd, |
| 19 base::FilePath path, |
| 20 int id, |
| 21 InputDeviceType type, |
| 22 CursorDelegateEvdev* cursor, |
| 23 const EventDeviceInfo& info, |
| 24 DeviceEventDispatcherEvdev* dispatcher) |
| 25 : EventConverterEvdev(fd, |
| 26 path, |
| 27 id, |
| 28 type, |
| 29 info.name(), |
| 30 info.vendor_id(), |
| 31 info.product_id()), |
| 32 cursor_(cursor), |
| 33 dispatcher_(dispatcher) { |
| 34 x_abs_min_ = info.GetAbsMinimum(ABS_X); |
| 35 x_abs_range_ = info.GetAbsMaximum(ABS_X) - x_abs_min_ + 1; |
| 36 y_abs_min_ = info.GetAbsMinimum(ABS_Y); |
| 37 y_abs_range_ = info.GetAbsMaximum(ABS_Y) - y_abs_min_ + 1; |
| 38 } |
| 39 |
| 40 TabletEventConverterEvdev::~TabletEventConverterEvdev() { |
| 41 } |
| 42 |
| 43 void TabletEventConverterEvdev::OnFileCanReadWithoutBlocking(int fd) { |
| 44 TRACE_EVENT1("evdev", |
| 45 "TabletEventConverterEvdev::OnFileCanReadWithoutBlocking", "fd", |
| 46 fd); |
| 47 |
| 48 input_event inputs[4]; |
| 49 ssize_t read_size = read(fd, inputs, sizeof(inputs)); |
| 50 if (read_size < 0) { |
| 51 if (errno == EINTR || errno == EAGAIN) |
| 52 return; |
| 53 if (errno != ENODEV) |
| 54 PLOG(ERROR) << "error reading device " << path_.value(); |
| 55 Stop(); |
| 56 return; |
| 57 } |
| 58 |
| 59 if (!enabled_) |
| 60 return; |
| 61 |
| 62 DCHECK_EQ(read_size % sizeof(*inputs), 0u); |
| 63 ProcessEvents(inputs, read_size / sizeof(*inputs)); |
| 64 } |
| 65 |
| 66 void TabletEventConverterEvdev::ProcessEvents(const input_event* inputs, |
| 67 int count) { |
| 68 for (int i = 0; i < count; ++i) { |
| 69 const input_event& input = inputs[i]; |
| 70 switch (input.type) { |
| 71 case EV_KEY: |
| 72 ConvertKeyEvent(input); |
| 73 break; |
| 74 case EV_ABS: |
| 75 ConvertAbsEvent(input); |
| 76 break; |
| 77 case EV_SYN: |
| 78 FlushEvents(input); |
| 79 break; |
| 80 } |
| 81 } |
| 82 } |
| 83 |
| 84 void TabletEventConverterEvdev::ConvertKeyEvent(const input_event& input) { |
| 85 // Only handle other events if we have a stylus in proximity |
| 86 if (input.code >= BTN_TOOL_PEN && input.code <= BTN_TOOL_LENS) { |
| 87 if (input.value == 1) |
| 88 stylus_ = input.code; |
| 89 else if (input.value == 0) |
| 90 stylus_ = 0; |
| 91 else |
| 92 LOG(WARNING) << "Unexpected value: " << input.value |
| 93 << " for code: " << input.code; |
| 94 } |
| 95 |
| 96 if (input.code >= BTN_TOUCH && input.code <= BTN_STYLUS2) { |
| 97 DispatchMouseButton(input); |
| 98 return; |
| 99 } |
| 100 } |
| 101 |
| 102 void TabletEventConverterEvdev::ConvertAbsEvent(const input_event& input) { |
| 103 if (!cursor_) |
| 104 return; |
| 105 |
| 106 switch (input.code) { |
| 107 case ABS_X: |
| 108 x_abs_location_ = input.value; |
| 109 abs_value_dirty_ = true; |
| 110 break; |
| 111 case ABS_Y: |
| 112 y_abs_location_ = input.value; |
| 113 abs_value_dirty_ = true; |
| 114 break; |
| 115 } |
| 116 } |
| 117 |
| 118 void TabletEventConverterEvdev::UpdateCursor() { |
| 119 gfx::Rect confined_bounds = cursor_->GetCursorConfinedBounds(); |
| 120 |
| 121 int x = |
| 122 ((x_abs_location_ - x_abs_min_) * confined_bounds.width()) / x_abs_range_; |
| 123 int y = ((y_abs_location_ - y_abs_min_) * confined_bounds.height()) / |
| 124 y_abs_range_; |
| 125 |
| 126 x += confined_bounds.x(); |
| 127 y += confined_bounds.y(); |
| 128 |
| 129 cursor_->MoveCursorTo(gfx::PointF(x, y)); |
| 130 } |
| 131 |
| 132 void TabletEventConverterEvdev::DispatchMouseButton(const input_event& input) { |
| 133 if (!cursor_) |
| 134 return; |
| 135 |
| 136 unsigned int button; |
| 137 // These are the same as X11 behaviour |
| 138 if (input.code == BTN_TOUCH) |
| 139 button = BTN_LEFT; |
| 140 else if (input.code == BTN_STYLUS2) |
| 141 button = BTN_RIGHT; |
| 142 else if (input.code == BTN_STYLUS) |
| 143 button = BTN_MIDDLE; |
| 144 else |
| 145 return; |
| 146 |
| 147 if (abs_value_dirty_) { |
| 148 UpdateCursor(); |
| 149 abs_value_dirty_ = false; |
| 150 } |
| 151 |
| 152 bool down = input.value; |
| 153 |
| 154 dispatcher_->DispatchMouseButtonEvent(MouseButtonEventParams( |
| 155 input_device_.id, cursor_->GetLocation(), button, down, |
| 156 false /* allow_remap */, TimeDeltaFromInputEvent(input))); |
| 157 } |
| 158 |
| 159 void TabletEventConverterEvdev::FlushEvents(const input_event& input) { |
| 160 if (!cursor_) |
| 161 return; |
| 162 |
| 163 // Prevent propagation of invalid data on stylus lift off |
| 164 if (stylus_ == 0) { |
| 165 abs_value_dirty_ = false; |
| 166 return; |
| 167 } |
| 168 |
| 169 if (!abs_value_dirty_) |
| 170 return; |
| 171 |
| 172 UpdateCursor(); |
| 173 |
| 174 dispatcher_->DispatchMouseMoveEvent( |
| 175 MouseMoveEventParams(input_device_.id, cursor_->GetLocation(), |
| 176 TimeDeltaFromInputEvent(input))); |
| 177 |
| 178 abs_value_dirty_ = false; |
| 179 } |
| 180 |
| 181 } // namespace ui |
OLD | NEW |