OLD | NEW |
| (Empty) |
1 // Copyright (c) 2013 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/touch_event_converter_ozone.h" | |
6 | |
7 #include <fcntl.h> | |
8 #include <linux/input.h> | |
9 #include <poll.h> | |
10 #include <stdio.h> | |
11 #include <unistd.h> | |
12 | |
13 #include <cmath> | |
14 #include <limits> | |
15 | |
16 #include "base/bind.h" | |
17 #include "base/callback.h" | |
18 #include "base/logging.h" | |
19 #include "base/message_loop/message_loop.h" | |
20 #include "base/message_loop/message_pump_ozone.h" | |
21 #include "ui/events/event.h" | |
22 #include "ui/events/event_constants.h" | |
23 #include "ui/gfx/ozone/surface_factory_ozone.h" | |
24 | |
25 namespace { | |
26 | |
27 // Number is determined empirically. | |
28 // TODO(rjkroege): Configure this per device. | |
29 const float kFingerWidth = 25.f; | |
30 | |
31 } // namespace | |
32 | |
33 namespace ui { | |
34 | |
35 TouchEventConverterOzone::TouchEventConverterOzone(int fd, int id) | |
36 : pressure_min_(0), | |
37 pressure_max_(0), | |
38 x_scale_(1.), | |
39 y_scale_(1.), | |
40 x_max_(std::numeric_limits<int>::max()), | |
41 y_max_(std::numeric_limits<int>::max()), | |
42 current_slot_(0), | |
43 fd_(fd), | |
44 id_(id) { | |
45 Init(); | |
46 } | |
47 | |
48 TouchEventConverterOzone::~TouchEventConverterOzone() { | |
49 if (close(fd_) < 0) | |
50 DLOG(WARNING) << "failed close on /dev/input/event" << id_; | |
51 } | |
52 | |
53 void TouchEventConverterOzone::Init() { | |
54 input_absinfo abs = {}; | |
55 if (ioctl(fd_, EVIOCGABS(ABS_MT_SLOT), &abs) != -1) { | |
56 CHECK_GE(abs.maximum, abs.minimum); | |
57 CHECK_GE(abs.minimum, 0); | |
58 } else { | |
59 DLOG(WARNING) << "failed ioctl EVIOCGABS ABS_MT_SLOT event" << id_; | |
60 } | |
61 if (ioctl(fd_, EVIOCGABS(ABS_MT_PRESSURE), &abs) != -1) { | |
62 pressure_min_ = abs.minimum; | |
63 pressure_max_ = abs.maximum; | |
64 } else { | |
65 DLOG(WARNING) << "failed ioctl EVIOCGABS ABS_MT_PRESSURE event" << id_; | |
66 } | |
67 int x_min = 0, x_max = 0; | |
68 if (ioctl(fd_, EVIOCGABS(ABS_MT_POSITION_X), &abs) != -1) { | |
69 x_min = abs.minimum; | |
70 x_max = abs.maximum; | |
71 } else { | |
72 LOG(WARNING) << "failed ioctl EVIOCGABS ABS_X event" << id_; | |
73 } | |
74 int y_min = 0, y_max = 0; | |
75 if (ioctl(fd_, EVIOCGABS(ABS_MT_POSITION_Y), &abs) != -1) { | |
76 y_min = abs.minimum; | |
77 y_max = abs.maximum; | |
78 } else { | |
79 LOG(WARNING) << "failed ioctl EVIOCGABS ABS_Y event" << id_; | |
80 } | |
81 if (x_max && y_max && gfx::SurfaceFactoryOzone::GetInstance()) { | |
82 const char* display = | |
83 gfx::SurfaceFactoryOzone::GetInstance()->DefaultDisplaySpec(); | |
84 int screen_width, screen_height; | |
85 int sc = sscanf(display, "%dx%d", &screen_width, &screen_height); | |
86 if (sc == 2) { | |
87 x_scale_ = (double)screen_width / (x_max - x_min); | |
88 y_scale_ = (double)screen_height / (y_max - y_min); | |
89 x_max_ = screen_width - 1; | |
90 y_max_ = screen_height - 1; | |
91 LOG(INFO) << "touch input x_scale=" << x_scale_ | |
92 << " y_scale=" << y_scale_; | |
93 } else { | |
94 LOG(WARNING) << "malformed display spec from " | |
95 << "SurfaceFactoryOzone::DefaultDisplaySpec"; | |
96 } | |
97 } | |
98 } | |
99 | |
100 void TouchEventConverterOzone::OnFileCanWriteWithoutBlocking(int /* fd */) { | |
101 // Read-only file-descriptors. | |
102 NOTREACHED(); | |
103 } | |
104 | |
105 void TouchEventConverterOzone::OnFileCanReadWithoutBlocking(int fd) { | |
106 input_event inputs[MAX_FINGERS * 6 + 1]; | |
107 ssize_t read_size = read(fd, inputs, sizeof(inputs)); | |
108 if (read_size <= 0) | |
109 return; | |
110 | |
111 for (unsigned i = 0; i < read_size / sizeof(*inputs); i++) { | |
112 const input_event& input = inputs[i]; | |
113 if (input.type == EV_ABS) { | |
114 switch (input.code) { | |
115 case ABS_MT_TOUCH_MAJOR: | |
116 altered_slots_.set(current_slot_); | |
117 events_[current_slot_].major_ = input.value; | |
118 break; | |
119 case ABS_X: | |
120 case ABS_MT_POSITION_X: | |
121 altered_slots_.set(current_slot_); | |
122 events_[current_slot_].x_ = roundf(input.value * x_scale_); | |
123 break; | |
124 case ABS_Y: | |
125 case ABS_MT_POSITION_Y: | |
126 altered_slots_.set(current_slot_); | |
127 events_[current_slot_].y_ = roundf(input.value * y_scale_); | |
128 break; | |
129 case ABS_MT_TRACKING_ID: | |
130 altered_slots_.set(current_slot_); | |
131 if (input.value < 0) { | |
132 events_[current_slot_].type_ = ET_TOUCH_RELEASED; | |
133 } else { | |
134 events_[current_slot_].finger_ = input.value; | |
135 events_[current_slot_].type_ = ET_TOUCH_PRESSED; | |
136 } | |
137 break; | |
138 case ABS_MT_PRESSURE: | |
139 case ABS_PRESSURE: | |
140 altered_slots_.set(current_slot_); | |
141 events_[current_slot_].pressure_ = input.value - pressure_min_; | |
142 events_[current_slot_].pressure_ /= pressure_max_ - pressure_min_; | |
143 break; | |
144 case ABS_MT_SLOT: | |
145 current_slot_ = input.value; | |
146 altered_slots_.set(current_slot_); | |
147 break; | |
148 default: | |
149 NOTREACHED(); | |
150 } | |
151 } else if (input.type == EV_SYN) { | |
152 switch (input.code) { | |
153 case SYN_REPORT: | |
154 for (int j = 0; j < MAX_FINGERS; j++) { | |
155 if (altered_slots_[j]) { | |
156 // TODO(rjkroege): Support elliptical finger regions. | |
157 scoped_ptr<TouchEvent> tev(new TouchEvent( | |
158 events_[j].type_, | |
159 gfx::Point(std::min(x_max_, events_[j].x_), | |
160 std::min(y_max_, events_[j].y_)), | |
161 /* flags */ 0, | |
162 /* touch_id */ j, | |
163 base::TimeDelta::FromMicroseconds( | |
164 input.time.tv_sec * 1000000 + input.time.tv_usec), | |
165 events_[j].pressure_ * kFingerWidth, | |
166 events_[j].pressure_ * kFingerWidth, | |
167 /* angle */ 0., | |
168 events_[j].pressure_)); | |
169 DispatchEvent(tev.PassAs<ui::Event>()); | |
170 | |
171 // Subsequent events for this finger will be touch-move until it | |
172 // is released. | |
173 events_[j].type_ = ET_TOUCH_MOVED; | |
174 } | |
175 } | |
176 altered_slots_.reset(); | |
177 break; | |
178 case SYN_MT_REPORT: | |
179 case SYN_CONFIG: | |
180 case SYN_DROPPED: | |
181 NOTREACHED() << "SYN_MT events not supported."; | |
182 break; | |
183 } | |
184 } else { | |
185 NOTREACHED(); | |
186 } | |
187 } | |
188 } | |
189 | |
190 } // namespace ui | |
OLD | NEW |