1 /***************************************************************************
3 * Copyright 2010, 2011 BMW Car IT GmbH
4 * Copyright (C) 2011 DENSO CORPORATION and Robert Bosch Car Multimedia Gmbh
7 * Licensed under the Apache License, Version 2.0 (the "License");
8 * you may not use this file except in compliance with the License.
9 * You may obtain a copy of the License at
11 * http://www.apache.org/licenses/LICENSE-2.0
13 * Unless required by applicable law or agreed to in writing, software
14 * distributed under the License is distributed on an "AS IS" BASIS,
15 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16 * See the License for the specific language governing permissions and
17 * limitations under the License.
20 * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS
21 * SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
22 * FITNESS, IN NO EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY
23 * SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER
24 * RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF
25 * CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
26 * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
28 ****************************************************************************/
32 #include <linux/input.h>
41 #include "InputManager.h"
42 #include "WindowSystems/WaylandEvdevInputEvent.h"
44 #define ARRAY_LENGTH(a) (sizeof (a) / sizeof (a)[0])
46 #define WL_UNUSED(A) (A)=(A)
47 static const char default_seat[] = "seat0";
49 // copied from udev/extras/input_id/input_id.c
50 // we must use this kernel-compatible implementation
51 #define BITS_PER_LONG (sizeof(unsigned long) * 8)
52 #define NBITS(x) ((((x)-1)/BITS_PER_LONG)+1)
53 #define OFF(x) ((x)%BITS_PER_LONG)
54 #define BIT(x) (1UL<<OFF(x))
55 #define LONG(x) ((x)/BITS_PER_LONG)
56 #define TEST_BIT(array, bit) ((array[LONG(bit)] >> OFF(bit)) & 1)
59 #define MAX_VELOCITY_DIFF 1.0
60 #define MOTION_TIMEOUT 300 // (ms)
61 #define NUM_POINTER_TRACKERS 16
63 struct evdev_dispatch_interface touchpad_interface = {
64 WaylandEvdevInputEvent::touchpadProcess,
65 WaylandEvdevInputEvent::touchpadDestroy,
68 struct evdev_dispatch_interface fallback_interface = {
69 WaylandEvdevInputEvent::fallbackProcess,
70 WaylandEvdevInputEvent::fallbackDestroy,
73 // Function prototypes
74 void acceleratorFilter (struct motion_filter *, struct motion_params *, void *, uint32_t);
75 void acceleratorDestroy(struct motion_filter *);
77 struct motion_filter_interface accelerator_interface = {
82 static struct touchpad_model_spec touchpad_spec_table[] = {
83 {0x0002, 0x0007, TOUCHPAD_MODEL_SYNAPTICS},
84 {0x0002, 0x0008, TOUCHPAD_MODEL_ALPS},
85 {0x05ac, 0x0000, TOUCHPAD_MODEL_APPLETOUCH},
86 {0x0002, 0x000e, TOUCHPAD_MODEL_ELANTECH},
87 {0x0000, 0x0000, TOUCHPAD_MODEL_UNKNOWN}
90 ////////////////////////////////////////////////////////////////////////////
93 isMotionEvent(struct input_event *e)
107 case ABS_MT_POSITION_X:
108 case ABS_MT_POSITION_Y:
116 static enum touchpad_model
117 getTouchpadModel(struct evdev_input_device *device)
122 if (ioctl(device->fd, EVIOCGID, &id) < 0)
123 return TOUCHPAD_MODEL_UNKNOWN;
125 for (i = 0; i < sizeof(touchpad_spec_table); ++i){
126 if (touchpad_spec_table[i].vendor == id.vendor &&
127 (!touchpad_spec_table[i].product ||
128 touchpad_spec_table[i].product == id.product)){
129 return touchpad_spec_table[i].model;
133 return TOUCHPAD_MODEL_UNKNOWN;
137 configureTouchpadPressure(struct touchpad_dispatch *touchpad,
138 int32_t pressure_min, int32_t pressure_max)
140 int32_t range = pressure_max - pressure_min + 1;
141 touchpad->has_pressure = 1;
143 // Magic numbers from xf86-input-synaptics
144 switch (touchpad->model){
145 case TOUCHPAD_MODEL_ELANTECH:
146 touchpad->pressure.touch_low = pressure_min + 1;
147 touchpad->pressure.touch_high = pressure_min + 1;
150 touchpad->pressure.touch_low = pressure_min + range * (25.0/256.0);
151 touchpad->pressure.touch_high = pressure_min + range * (30.0/256.0);
155 touchpad->pressure.press = pressure_min + range;
159 touchpadProfile(struct motion_filter *filter, void *data,
160 double velocity, uint32_t time)
164 struct touchpad_dispatch *touchpad = (struct touchpad_dispatch*)data;
167 accel_factor = velocity * touchpad->constant_accel_factor;
169 if (accel_factor > touchpad->max_accel_factor)
170 accel_factor = touchpad->max_accel_factor;
171 else if (accel_factor < touchpad->min_accel_factor)
172 accel_factor = touchpad->min_accel_factor;
177 static motion_filter*
178 createPointerAccelatorFilter(accel_profile_func_t profile)
180 struct pointer_accelerator *filter;
182 filter = (struct pointer_accelerator*)malloc(sizeof(*filter));
186 filter->base.interface = &accelerator_interface;
187 wl_list_init(&filter->base.link);
189 filter->profile = profile;
190 filter->last_velocity = 0.0;
194 filter->trackers = (struct pointer_tracker*)
195 calloc(NUM_POINTER_TRACKERS, sizeof(*filter->trackers));
196 filter->cur_tracker = 0;
198 return &filter->base;
201 static evdev_dispatch*
202 createFallbackDispatch()
204 struct evdev_dispatch *dispatch =
205 (struct evdev_dispatch*)malloc(sizeof(*dispatch));
206 if (dispatch == NULL)
209 dispatch->interface = &fallback_interface;
214 ////////////////////////////////////////////////////////////////////////
217 processTouch(struct evdev_input_device *device, struct input_event *e,
218 int screen_width, int screen_height)
222 device->mt.slot = e->value;
224 case ABS_MT_TRACKING_ID:
226 device->pending_events |= EVDEV_ABSOLUTE_MT_DOWN;
228 device->pending_events |= EVDEV_ABSOLUTE_MT_UP;
230 case ABS_MT_POSITION_X:
231 device->mt.x[device->mt.slot] =
232 (e->value - device->abs.min_x) * screen_width /
233 (device->abs.max_x - device->abs.min_x) +
234 0; //device->output->x;
235 device->pending_events |= EVDEV_ABSOLUTE_MT_MOTION;
237 case ABS_MT_POSITION_Y:
238 device->mt.y[device->mt.slot] =
239 (e->value - device->abs.min_y) * screen_height /
240 (device->abs.max_y - device->abs.min_y) +
241 0; //device->output->y;
242 device->pending_events |= EVDEV_ABSOLUTE_MT_MOTION;
248 processAbsoluteMotion(struct evdev_input_device *device, struct input_event *e,
249 int screen_width, int screen_height)
254 (e->value - device->abs.min_x) * screen_width /
255 (device->abs.max_x - device->abs.min_x) +
256 0; //device->output->x;
257 device->pending_events |= EVDEV_ABSOLUTE_MOTION;
261 (e->value - device->abs.min_y) * screen_height /
262 (device->abs.max_y - device->abs.min_y) +
263 0; //device->output->y;
264 device->abs.x = screen_width - device->abs.x;
265 device->pending_events |= EVDEV_ABSOLUTE_MOTION;
267 // The following is the effective code only from a specific model
270 device->abs.y = (e->value - device->abs.min_x) * screen_height /
271 (device->abs.max_x - device->abs.min_x);
272 device->pending_events |= EVDEV_ABSOLUTE_MOTION;
275 device->abs.x = (e->value - device->abs.min_y) * screen_width /
276 (device->abs.max_y - device->abs.min_y);
277 device->abs.x = screen_width - device->abs.x;
278 device->pending_events |= EVDEV_ABSOLUTE_MOTION;
284 ////////////////////////////////////////////////////////////////////////
287 hysteresis(int in, int center, int margin)
289 int diff = in - center;
290 if (abs(diff) <= margin)
294 return center + diff - margin;
295 else if (diff < -margin)
296 return center + diff + margin;
297 return center + diff;
300 static inline struct touchpad_motion*
301 motionHistoryOffset(struct touchpad_dispatch *touchpad, int offset)
304 (touchpad->motion_index - offset + TOUCHPAD_HISTORY_LENGTH) %
305 TOUCHPAD_HISTORY_LENGTH;
307 return &touchpad->motion_history[offsetIndex];
311 estimateDelta(int x0, int x1, int x2, int x3)
313 return (x0 + x1 - x2 - x3) / 4;
317 touchpadGetDelta(struct touchpad_dispatch *touchpad, double *dx, double *dy)
319 *dx = estimateDelta(motionHistoryOffset(touchpad, 0)->x,
320 motionHistoryOffset(touchpad, 1)->x,
321 motionHistoryOffset(touchpad, 2)->x,
322 motionHistoryOffset(touchpad, 3)->x);
323 *dy = estimateDelta(motionHistoryOffset(touchpad, 0)->y,
324 motionHistoryOffset(touchpad, 1)->y,
325 motionHistoryOffset(touchpad, 2)->y,
326 motionHistoryOffset(touchpad, 3)->y);
330 filterDispatch(struct motion_filter *filter, struct motion_params *motion,
331 void *data, uint32_t time)
333 filter->interface->filter(filter, motion, data, time);
337 filterMotion(struct touchpad_dispatch *touchpad,
338 double *dx, double *dy, uint32_t time)
340 struct motion_filter *filter;
341 struct motion_params motion;
346 wl_list_for_each(filter, &touchpad->motion_filters, link){
347 filterDispatch(filter, &motion, touchpad, time);
355 getDirection(int dx, int dy)
357 int dir = UNDEFINED_DIRECTION;
361 if (abs(dx) < 2 && abs(dy) < 2) {
362 if (dx > 0 && dy > 0)
364 else if (dx > 0 && dy < 0)
366 else if (dx < 0 && dy > 0)
368 else if (dx < 0 && dy < 0)
380 // Calculate r within the interval [0 to 8)
382 // r = [0 .. 2Ï€] where 0 is North
383 // d_f = r / 2Ï€ ([0 .. 1))
387 r = fmod(r + 2.5*M_PI, 2*M_PI);
390 // Mark one or two close enough octants
391 d1 = (int)(r + 0.9) % 8;
392 d2 = (int)(r + 0.1) % 8;
394 dir = (1 << d1) | (1 << d2);
401 feedTrackers(struct pointer_accelerator *accel,
402 double dx, double dy, uint32_t time)
405 struct pointer_tracker *trackers = accel->trackers;
407 for (i = 0; i < NUM_POINTER_TRACKERS; ++i){
408 trackers[i].dx += dx;
409 trackers[i].dy += dy;
412 current = (accel->cur_tracker + 1) % NUM_POINTER_TRACKERS;
413 accel->cur_tracker = current;
415 trackers[current].dx = 0.0;
416 trackers[current].dy = 0.0;
417 trackers[current].time = time;
418 trackers[current].dir = getDirection(dx, dy);
421 static struct pointer_tracker*
422 trackerByOffset(struct pointer_accelerator *accel, unsigned int offset)
425 (accel->cur_tracker + NUM_POINTER_TRACKERS - offset)
426 % NUM_POINTER_TRACKERS;
427 return &accel->trackers[index];
431 calculateTrackerVelocity(struct pointer_tracker *tracker, uint32_t time)
439 distance = sqrt(dx*dx + dy*dy);
440 return distance / (double)(time - tracker->time);
444 calculateVelocity(struct pointer_accelerator *accel, uint32_t time)
446 struct pointer_tracker *tracker;
449 double initial_velocity;
450 double velocity_diff;
453 unsigned int dir = trackerByOffset(accel, 0)->dir;
455 // Find first velocity
456 for (offset = 1; offset < NUM_POINTER_TRACKERS; offset++) {
457 tracker = trackerByOffset(accel, offset);
459 if (time <= tracker->time)
462 result = initial_velocity =
463 calculateTrackerVelocity(tracker, time);
464 if (initial_velocity > 0.0)
468 // Find least recent vector within a timelimit, maximum velocity diff
469 // and direction threshold.
470 for (; offset < NUM_POINTER_TRACKERS; offset++) {
471 tracker = trackerByOffset(accel, offset);
473 // Stop if too far away in time
474 if (time - tracker->time > MOTION_TIMEOUT ||
475 tracker->time > time)
478 // Stop if direction changed
483 velocity = calculateTrackerVelocity(tracker, time);
485 // Stop if velocity differs too much from initial
486 velocity_diff = fabs(initial_velocity - velocity);
487 if (velocity_diff > MAX_VELOCITY_DIFF)
497 accelerationProfile(struct pointer_accelerator *accel,
498 void *data, double velocity, uint32_t time)
500 return accel->profile(&accel->base, data, velocity, time);
504 calculateAcceleration(struct pointer_accelerator *accel,
505 void *data, double velocity, uint32_t time)
509 factor = accelerationProfile(accel, data, velocity, time);
510 factor += accelerationProfile(accel, data, accel->last_velocity, time);
512 accelerationProfile(accel, data,
513 (accel->last_velocity + velocity) / 2,
515 factor = factor / 6.0;
520 softenDelta(double lastDelta, double delta)
522 if (delta < -1.0 || delta > 1.0){
523 if (delta > lastDelta)
525 else if (delta < lastDelta)
532 applySoftening(struct pointer_accelerator *accel,
533 struct motion_params *motion)
535 motion->dx = softenDelta(accel->last_dx, motion->dx);
536 motion->dy = softenDelta(accel->last_dy, motion->dy);
540 acceleratorFilter(struct motion_filter *filter, struct motion_params *motion,
541 void *data, uint32_t time)
543 struct pointer_accelerator *accel = (struct pointer_accelerator*)filter;
547 feedTrackers(accel, motion->dx, motion->dy, time);
548 velocity = calculateVelocity(accel, time);
549 accel_value = calculateAcceleration(accel, data, velocity, time);
551 motion->dx = accel_value * motion->dx;
552 motion->dy = accel_value * motion->dy;
554 applySoftening(accel, motion);
556 accel->last_dx = motion->dx;
557 accel->last_dy = motion->dy;
559 accel->last_velocity = velocity;
563 acceleratorDestroy(struct motion_filter *filter)
565 struct pointer_accelerator *accel = (struct pointer_accelerator*)filter;
567 free(accel->trackers);
571 /// WaylandEvdevInputEvent /////////////////////////////////////////////////
573 WaylandEvdevInputEvent::WaylandEvdevInputEvent(WaylandBaseWindowSystem* windowSystem)
574 : WaylandInputEvent(windowSystem)
579 wl_list_init(&m_deviceList);
582 WaylandEvdevInputEvent::~WaylandEvdevInputEvent()
588 struct evdev_input_device *device, *next;
590 wl_list_for_each_safe(device, next, &m_deviceList, link){
591 removeDevice(device);
596 WaylandEvdevInputEvent::removeDevice(struct evdev_input_device *device)
598 struct evdev_dispatch *dispatch = device->dispatch;
601 dispatch->interface->destroy(dispatch);
603 wl_event_source_remove(device->source);
604 wl_list_remove(&device->link);
606 mtdev_close_delete(device->mtdev);
608 free(device->devnode);
613 WaylandEvdevInputEvent::setupInputEvent()
615 LOG_INFO("WaylandEvdevInputEvent", "setupInputEvent IN");
617 WaylandInputEvent::setupInputEvent();
619 m_screenWidth = m_windowSystem->getWindowWidth();
620 m_screenHeight = m_windowSystem->getWindowHeight();
623 bool bRet = addDevices();
629 LOG_INFO("WaylandEvdevInputEvent", "setupInputEvent OUT");
633 WaylandEvdevInputEvent::addDevices()
638 LOG_ERROR("WaylandEvdevInputEvent", "Failed to initialize udev context");
642 struct udev_enumerate *e = udev_enumerate_new(m_udev);
643 udev_enumerate_add_match_subsystem(e, "input");
644 udev_enumerate_scan_devices(e);
646 struct udev_list_entry *entry;
647 const char *path, *sysname;
648 struct udev_device *device;
649 udev_list_entry_foreach(entry, udev_enumerate_get_list_entry(e)){
650 path = udev_list_entry_get_name(entry);
651 device = udev_device_new_from_syspath(m_udev, path);
653 sysname = udev_device_get_sysname(device);
654 if (strncmp("event", sysname, 5) != 0){
655 udev_device_unref(device);
660 udev_device_unref(device);
662 udev_enumerate_unref(e);
664 notifyKeyboardFocus();
666 if (wl_list_empty(&m_deviceList)){
667 LOG_WARNING("WaylandEvdevInputEvent", "No input devices on entering service");
674 WaylandEvdevInputEvent::addDevice(struct udev_device *udevDevice)
677 const char *device_seat;
679 device_seat = udev_device_get_property_value(udevDevice, "ID_SEAT");
681 device_seat = default_seat;
683 devnode = udev_device_get_devnode(udevDevice);
684 createInputDevice(m_windowSystem->getNativeDisplayHandle(), devnode);
688 WaylandEvdevInputEvent::createInputDevice(struct wl_display *display, const char *path)
690 struct evdev_input_device *device;
691 struct wl_event_loop *eventLoop;
693 device = (struct evdev_input_device*)malloc(sizeof(*device));
698 device->master = this;
700 device->mtdev = NULL;
701 device->devnode = strdup(path);
702 device->mt.slot = -1;
705 device->dispatch = NULL;
707 device->fd = open(path, O_RDWR | O_NONBLOCK);
712 if (configureDevice(device) < 0){
716 // If the dispatch was not set up use the fallback
717 if (device->dispatch == NULL)
718 device->dispatch = createFallbackDispatch();
719 if (device->dispatch == NULL)
723 device->mtdev = mtdev_new_open(device->fd);
725 LOG_WARNING("WaylandEvdevInputEvent", "mtdev failed to open for " << path);
729 eventLoop = wl_display_get_event_loop(display);
730 device->source = wl_event_loop_add_fd(eventLoop, device->fd, WL_EVENT_READABLE,
731 WaylandEvdevInputEvent::handleInputEvent,
733 if (device->source == NULL){
737 wl_list_insert(m_deviceList.prev, &(device->link));
742 device->dispatch->interface->destroy(device->dispatch);
746 free(device->devnode);
752 WaylandEvdevInputEvent::configureDevice(struct evdev_input_device *device)
754 struct input_absinfo absinfo;
755 unsigned long ev_bits[NBITS(EV_MAX)];
756 unsigned long abs_bits[NBITS(ABS_MAX)];
757 unsigned long rel_bits[NBITS(ABS_MAX)];
758 unsigned long key_bits[NBITS(KEY_MAX)];
765 ioctl(device->fd, EVIOCGBIT(0, sizeof(ev_bits)), ev_bits);
766 if (TEST_BIT(ev_bits, EV_ABS)){
769 ioctl(device->fd, EVIOCGBIT(EV_ABS, sizeof(abs_bits)), abs_bits);
770 if (TEST_BIT(abs_bits, ABS_X)){
771 ioctl(device->fd, EVIOCGABS(ABS_X), &absinfo);
772 device->abs.min_x = absinfo.minimum;
773 device->abs.max_x = absinfo.maximum;
774 device->caps |= EVDEV_MOTION_ABS;
776 if (TEST_BIT(abs_bits, ABS_Y)){
777 ioctl(device->fd, EVIOCGABS(ABS_Y), &absinfo);
778 device->abs.min_y = absinfo.minimum;
779 device->abs.max_y = absinfo.maximum;
780 device->caps |= EVDEV_MOTION_ABS;
782 if (TEST_BIT(abs_bits, ABS_MT_SLOT)){
785 device->caps |= EVDEV_TOUCH;
788 if (TEST_BIT(ev_bits, EV_REL)){
789 ioctl(device->fd, EVIOCGBIT(EV_REL, sizeof(rel_bits)), rel_bits);
790 if (TEST_BIT(rel_bits, REL_X) || TEST_BIT(rel_bits, REL_Y)){
791 device->caps |= EVDEV_MOTION_REL;
794 if (TEST_BIT(ev_bits, EV_KEY)){
796 ioctl(device->fd, EVIOCGBIT(EV_KEY, sizeof(key_bits)), key_bits);
797 if (TEST_BIT(key_bits, BTN_TOOL_FINGER) &&
798 !TEST_BIT(key_bits, BTN_TOOL_PEN) && hasAbs){
799 device->dispatch = createTouchpad(device);
802 for (i = KEY_ESC; i < KEY_MAX; ++i){
803 if (i >= BTN_MISC && i < KEY_OK)
805 if (TEST_BIT(key_bits, i)){
806 device->caps |= EVDEV_KEYBOARD;
810 for (i = BTN_MISC; i < KEY_OK; ++i){
811 if (TEST_BIT(key_bits, i)){
812 device->caps |= EVDEV_BUTTON;
817 if (TEST_BIT(ev_bits, EV_LED)){
818 device->caps |= EVDEV_KEYBOARD;
821 // This rule tries to catch accelerometer devices and opt out. We may
822 // want to adjust the protocol later adding a proper event for dealing
823 // with accelerometers and implement here accordingly
824 if (hasAbs && !hasKey && !device->isMt)
828 fprintf(stdout, "DEVICE: [%s] information\n", device->devnode);
829 fprintf(stdout, " capabilities: EVDEV_KEYBOARD %s\n"
831 " EVDEV_MOTION_ABS %s\n"
832 " EVDEV_MOTION_REL %s\n"
834 (device->caps & EVDEV_KEYBOARD) ? "TRUE" : "FALSE",
835 (device->caps & EVDEV_BUTTON) ? "TRUE" : "FALSE",
836 (device->caps & EVDEV_MOTION_ABS) ? "TRUE" : "FALSE",
837 (device->caps & EVDEV_MOTION_REL) ? "TRUE" : "FALSE",
838 (device->caps & EVDEV_TOUCH) ? "TRUE" : "FALSE");
839 if (device->caps & EVDEV_MOTION_ABS){
840 fprintf(stdout, " abs: min_x(%4d), min_y(%4d)\n", device->abs.min_x, device->abs.min_y);
841 fprintf(stdout, " max_x(%4d), max_y(%4d)\n", device->abs.max_x, device->abs.max_y);
842 fprintf(stdout, " x(%4d), y(%4d)\n", device->abs.x, device->abs.y);
844 fprintf(stdout, "\n");
847 if ((device->caps & (EVDEV_MOTION_ABS | EVDEV_MOTION_REL | EVDEV_BUTTON))){
850 if ((device->caps & (EVDEV_KEYBOARD))){
851 initKeyboardDevice(NULL);
853 if ((device->caps & (EVDEV_TOUCH))){
861 WaylandEvdevInputEvent::notifyKeyboardFocus()
863 struct evdev_input_device *device;
864 struct wl_array keys;
865 char evdev_keys[(KEY_CNT + 7) / 8], all_keys[(KEY_CNT + 7) / 8];
870 memset(all_keys, 0, sizeof(all_keys));
871 wl_list_for_each(device, &m_deviceList, link){
872 memset(evdev_keys, 0, sizeof(evdev_keys));
873 ret = ioctl(device->fd, EVIOCGKEY(sizeof(evdev_keys)), evdev_keys);
875 LOG_WARNING("WaylandEvdevInputEvent", "Failed to get keys for device: " <<
879 for (i = 0; i < ARRAY_LENGTH(evdev_keys); ++i){
880 all_keys[i] |= evdev_keys[i];
884 wl_array_init(&keys);
885 for (i = 0; i < KEY_CNT; ++i){
886 set = all_keys[i >> 3] & (1 << (i & 7));
888 k = (uint32_t*)wl_array_add(&keys, sizeof(*k));
893 notifyKeyboardFocusIn(&keys, STATE_UPDATE_AUTOMATIC);
895 wl_array_release(&keys);
899 WaylandEvdevInputEvent::notifyKeyboardFocusIn(struct wl_array *keys,
900 enum key_state_update updateState)
902 struct wl_seat *wlSeat;
905 if ((wlSeat = m_inputDevice->seat()) == NULL){
908 if (!wlSeat->keyboard){
911 serial = wl_display_next_serial(m_inputDevice->display());
912 wl_array_init(&wlSeat->keyboard->keys);
913 wl_array_copy(&wlSeat->keyboard->keys, keys);
915 struct wl_array *array = &wlSeat->keyboard->keys;
916 for (k = (uint32_t*)array->data;
917 (const char*)k < (const char*)array->data + array->size;
919 if (updateState == STATE_UPDATE_AUTOMATIC){
920 updateModifierState(wlSeat, serial, *k, WL_KEYBOARD_KEY_STATE_PRESSED);
926 WaylandEvdevInputEvent::updateModifierState(struct wl_seat *wlSeat, uint32_t serial,
927 uint32_t key, enum wl_keyboard_key_state state)
929 enum xkb_key_direction direction;
931 if (state == WL_KEYBOARD_KEY_STATE_PRESSED)
932 direction = XKB_KEY_DOWN;
934 direction = XKB_KEY_UP;
936 // Offset the keycode by 8, as the evdev XKB rules reflect X's
937 // broken keycode system, which starts at 8.
938 xkb_state_update_key(m_xkbState.state, key + 8, direction);
940 notifyModifiers(wlSeat, serial);
943 struct evdev_dispatch*
944 WaylandEvdevInputEvent::createTouchpad(struct evdev_input_device *device)
946 struct touchpad_dispatch *touchpad;
948 touchpad = (struct touchpad_dispatch*)malloc(sizeof(*touchpad));
949 if (touchpad == NULL)
952 touchpad->base.interface = &touchpad_interface;
954 touchpad->device = device;
955 wl_list_init(&touchpad->motion_filters);
957 configureTouchpad(touchpad, device);
959 return &touchpad->base;
963 WaylandEvdevInputEvent::configureTouchpad(struct touchpad_dispatch *touchpad,
964 struct evdev_input_device *device)
966 struct motion_filter *accel;
968 struct input_absinfo absinfo;
969 unsigned long abs_bits[NBITS(ABS_MAX)];
976 touchpad->model = getTouchpadModel(device);
978 // Configure pressure
979 ioctl(device->fd, EVIOCGBIT(EV_ABS, sizeof(abs_bits)), abs_bits);
980 if (TEST_BIT(abs_bits, ABS_PRESSURE)) {
981 ioctl(device->fd, EVIOCGABS(ABS_PRESSURE), &absinfo);
982 configureTouchpadPressure(touchpad,
987 // Configure acceleration factor
988 width = abs(device->abs.max_x - device->abs.min_x);
989 height = abs(device->abs.max_y - device->abs.min_y);
990 diagonal = sqrt(width*width + height*height);
992 touchpad->constant_accel_factor =
993 DEFAULT_CONSTANT_ACCEL_NUMERATOR / diagonal;
995 touchpad->min_accel_factor = DEFAULT_MIN_ACCEL_FACTOR;
996 touchpad->max_accel_factor = DEFAULT_MAX_ACCEL_FACTOR;
998 touchpad->hysteresis.margin_x = diagonal / DEFAULT_HYSTERESIS_MARGIN_DENOMINATOR;
999 touchpad->hysteresis.margin_y = diagonal / DEFAULT_HYSTERESIS_MARGIN_DENOMINATOR;
1000 touchpad->hysteresis.center_x = 0;
1001 touchpad->hysteresis.center_y = 0;
1003 // Configure acceleration profile
1004 accel = createPointerAccelatorFilter(touchpadProfile);
1005 wl_list_insert(&touchpad->motion_filters, &accel->link);
1007 // Setup initial state
1008 touchpad->reset = 1;
1010 memset(touchpad->motion_history, 0, sizeof touchpad->motion_history);
1011 touchpad->motion_index = 0;
1012 touchpad->motion_count = 0;
1014 touchpad->state = TOUCHPAD_STATE_NONE;
1015 touchpad->last_finger_state = 0;
1016 touchpad->finger_state = 0;
1020 WaylandEvdevInputEvent::handleInputEvent(int fd, uint32_t mask, void *data)
1024 struct evdev_input_device *device = (evdev_input_device*)data;
1025 struct input_event ev[32];
1029 len = mtdev_get(device->mtdev, fd, ev,
1030 ARRAY_LENGTH(ev)) * sizeof(struct input_event);
1033 len = read(fd, &ev, sizeof(ev));
1036 if (len < 0 || len % sizeof(ev[0]) != 0){
1040 WaylandEvdevInputEvent::processEvents(device, ev, len / sizeof(ev[0]));
1048 WaylandEvdevInputEvent::processEvents(struct evdev_input_device *device,
1049 struct input_event *ev,
1052 struct evdev_dispatch *dispatch = device->dispatch;
1053 struct input_event *e, *end;
1056 device->pending_events = 0;
1060 for (; e < end; ++e){
1061 time = e->time.tv_sec * 1000 + e->time.tv_usec / 1000;
1063 if (!isMotionEvent(e)){
1064 WaylandEvdevInputEvent::flushMotion(device, time);
1067 dispatch->interface->process(dispatch, device, e, time);
1070 WaylandEvdevInputEvent::flushMotion(device, time);
1074 WaylandEvdevInputEvent::flushMotion(struct evdev_input_device *device,
1077 if (!device->pending_events)
1080 WaylandEvdevInputEvent *inputEvent = static_cast<WaylandEvdevInputEvent*>(device->master);
1084 if (device->pending_events & EVDEV_RELATIVE_MOTION){
1085 struct wl_seat *wlSeat = inputEvent->inputDevice().seat();
1088 notifyMotion(device, time,
1089 wlSeat->pointer->x + device->rel.dx,
1090 wlSeat->pointer->y + device->rel.dy);
1092 device->pending_events &= ~EVDEV_RELATIVE_MOTION;
1096 if (device->pending_events & EVDEV_ABSOLUTE_MT_DOWN){
1098 notifyTouch(device);
1099 device->pending_events &= ~EVDEV_ABSOLUTE_MT_DOWN;
1100 device->pending_events &= ~EVDEV_ABSOLUTE_MT_MOTION;
1102 if (device->pending_events & EVDEV_ABSOLUTE_MT_MOTION){
1104 notifyTouch(device);
1105 device->pending_events &= ~EVDEV_ABSOLUTE_MT_DOWN;
1106 device->pending_events &= ~EVDEV_ABSOLUTE_MT_MOTION;
1108 if (device->pending_events & EVDEV_ABSOLUTE_MT_UP){
1110 notifyTouch(device);
1111 device->pending_events &= ~EVDEV_ABSOLUTE_MT_UP;
1113 if (device->pending_events & EVDEV_ABSOLUTE_MOTION){
1115 notifyMotion(device, time,
1116 wl_fixed_from_int(device->abs.x),
1117 wl_fixed_from_int(device->abs.y));
1118 device->pending_events &= ~EVDEV_ABSOLUTE_MOTION;
1122 /// Default event handler //////////////////////////////////////////////////
1125 WaylandEvdevInputEvent::fallbackProcess(struct evdev_dispatch *dispatch,
1126 struct evdev_input_device *device,
1127 struct input_event *e,
1130 WL_UNUSED(dispatch);
1134 evdevProcessRelative(device, time, e);
1137 evdevProcessAbsolute(device, e);
1140 evdevProcessKey(device, time, e);
1146 WaylandEvdevInputEvent::fallbackDestroy(struct evdev_dispatch *dispatch)
1148 if (dispatch) free(dispatch);
1152 WaylandEvdevInputEvent::evdevProcessRelative(struct evdev_input_device *device,
1153 uint32_t /*time*/, struct input_event *e)
1157 device->rel.dx += wl_fixed_from_int(e->value);
1158 device->pending_events |= EVDEV_RELATIVE_MOTION;
1161 device->rel.dy += wl_fixed_from_int(e->value);
1162 device->pending_events |= EVDEV_RELATIVE_MOTION;
1172 WaylandEvdevInputEvent::evdevProcessAbsolute(struct evdev_input_device *device,
1173 struct input_event *e)
1175 WaylandEvdevInputEvent *inputEvent = static_cast<WaylandEvdevInputEvent*>(device->master);
1179 int w = inputEvent->m_screenWidth;
1180 int h = inputEvent->m_screenHeight;
1183 processTouch(device, e, w, h);
1185 processAbsoluteMotion(device, e, w, h);
1190 WaylandEvdevInputEvent::evdevProcessKey(struct evdev_input_device *device,
1191 uint32_t time, struct input_event *e)
1207 notifyButton(device, time, e->code,
1208 e->value ? WL_POINTER_BUTTON_STATE_PRESSED
1209 : WL_POINTER_BUTTON_STATE_RELEASED);
1213 notifyKey(device, time, e->code,
1214 e->value ? WL_KEYBOARD_KEY_STATE_PRESSED
1215 : WL_KEYBOARD_KEY_STATE_RELEASED,
1221 /// Multi-touch event handler //////////////////////////////////////////////
1224 WaylandEvdevInputEvent::touchpadProcess(struct evdev_dispatch *dispatch,
1225 struct evdev_input_device *device,
1226 struct input_event *e,
1229 struct touchpad_dispatch *touchpad = (struct touchpad_dispatch*)dispatch;
1233 if (e->code == SYN_REPORT)
1234 touchpad->event_mask |= TOUCHPAD_EVENT_REPORT;
1237 touchpadProcessAbsolute(touchpad, device, e);
1240 touchpadProcessKey(touchpad, device, e, time);
1244 touchpadUpdateState(touchpad, time);
1248 WaylandEvdevInputEvent::touchpadDestroy(struct evdev_dispatch *dispatch)
1250 struct touchpad_dispatch *touchpad = (struct touchpad_dispatch*)dispatch;
1251 struct motion_filter *filter;
1252 struct motion_filter *next;
1254 wl_list_for_each_safe(filter, next, &touchpad->motion_filters, link){
1255 filter->interface->destroy(filter);
1258 if (dispatch) free(dispatch);
1262 WaylandEvdevInputEvent::touchpadProcessAbsolute(struct touchpad_dispatch *touchpad,
1263 struct evdev_input_device *device,
1264 struct input_event *e)
1270 if (e->value > touchpad->pressure.press)
1271 touchpad->state = TOUCHPAD_STATE_PRESS;
1272 else if (e->value > touchpad->pressure.touch_high)
1273 touchpad->state = TOUCHPAD_STATE_TOUCH;
1274 else if (e->value < touchpad->pressure.touch_low){
1275 if (touchpad->state > TOUCHPAD_STATE_NONE)
1276 touchpad->reset = 1;
1277 touchpad->state = TOUCHPAD_STATE_NONE;
1281 if (touchpad->state >= TOUCHPAD_STATE_TOUCH){
1282 touchpad->hw_abs.x = e->value;
1283 touchpad->event_mask |= TOUCHPAD_EVENT_ABSOLUTE_ANY;
1284 touchpad->event_mask |= TOUCHPAD_EVENT_ABSOLUTE_X;
1288 if (touchpad->state >= TOUCHPAD_STATE_TOUCH){
1289 touchpad->hw_abs.y = e->value;
1290 touchpad->event_mask |= TOUCHPAD_EVENT_ABSOLUTE_ANY;
1291 touchpad->event_mask |= TOUCHPAD_EVENT_ABSOLUTE_Y;
1298 WaylandEvdevInputEvent::touchpadProcessKey(struct touchpad_dispatch *touchpad,
1299 struct evdev_input_device * device,
1300 struct input_event *e,
1305 if (!touchpad->has_pressure){
1307 touchpad->state = TOUCHPAD_STATE_NONE;
1308 touchpad->reset = 1;
1311 touchpad->state = e->value ? TOUCHPAD_STATE_TOUCH
1312 : TOUCHPAD_STATE_NONE;
1325 notifyButton(device, time, e->code,
1326 e->value ? WL_POINTER_BUTTON_STATE_PRESSED
1327 : WL_POINTER_BUTTON_STATE_RELEASED);
1330 case BTN_TOOL_RUBBER:
1331 case BTN_TOOL_BRUSH:
1332 case BTN_TOOL_PENCIL:
1333 case BTN_TOOL_AIRBRUSH:
1334 case BTN_TOOL_MOUSE:
1336 touchpad->reset = 1;
1338 case BTN_TOOL_FINGER:
1339 touchpad->finger_state =
1340 ~TOUCHPAD_FINGERS_ONE | e->value ? TOUCHPAD_FINGERS_ONE : 0;
1342 case BTN_TOOL_DOUBLETAP:
1343 touchpad->finger_state =
1344 ~TOUCHPAD_FINGERS_TWO | e->value ? TOUCHPAD_FINGERS_TWO : 0;
1346 case BTN_TOOL_TRIPLETAP:
1347 touchpad->finger_state =
1348 ~TOUCHPAD_FINGERS_THREE | e->value ? TOUCHPAD_FINGERS_THREE : 0;
1354 WaylandEvdevInputEvent::touchpadUpdateState(struct touchpad_dispatch *touchpad,
1358 int center_x, center_y;
1361 if (touchpad->reset ||
1362 touchpad->last_finger_state != touchpad->finger_state) {
1363 touchpad->reset = 0;
1364 touchpad->motion_count = 0;
1365 touchpad->event_mask = TOUCHPAD_EVENT_NONE;
1366 touchpad->event_mask_filter =
1367 TOUCHPAD_EVENT_ABSOLUTE_X | TOUCHPAD_EVENT_ABSOLUTE_Y;
1369 touchpad->last_finger_state = touchpad->finger_state;
1373 touchpad->last_finger_state = touchpad->finger_state;
1375 if (!(touchpad->event_mask & TOUCHPAD_EVENT_REPORT))
1378 touchpad->event_mask &= ~TOUCHPAD_EVENT_REPORT;
1380 if ((touchpad->event_mask & touchpad->event_mask_filter) !=
1381 touchpad->event_mask_filter)
1384 touchpad->event_mask_filter = TOUCHPAD_EVENT_ABSOLUTE_ANY;
1385 touchpad->event_mask = 0;
1387 // Avoid noice by moving center only when delta reaches a threshold
1388 // distance from the old center
1389 if (touchpad->motion_count > 0) {
1390 center_x = hysteresis(touchpad->hw_abs.x,
1391 touchpad->hysteresis.center_x,
1392 touchpad->hysteresis.margin_x);
1393 center_y = hysteresis(touchpad->hw_abs.y,
1394 touchpad->hysteresis.center_y,
1395 touchpad->hysteresis.margin_y);
1398 center_x = touchpad->hw_abs.x;
1399 center_y = touchpad->hw_abs.y;
1401 touchpad->hysteresis.center_x = center_x;
1402 touchpad->hysteresis.center_y = center_y;
1403 touchpad->hw_abs.x = center_x;
1404 touchpad->hw_abs.y = center_y;
1406 // Update motion history tracker
1407 motion_index = (touchpad->motion_index + 1) % TOUCHPAD_HISTORY_LENGTH;
1408 touchpad->motion_index = motion_index;
1409 touchpad->motion_history[motion_index].x = touchpad->hw_abs.x;
1410 touchpad->motion_history[motion_index].y = touchpad->hw_abs.y;
1411 if (touchpad->motion_count < 4)
1412 touchpad->motion_count++;
1414 if (touchpad->motion_count >= 4) {
1415 touchpadGetDelta(touchpad, &dx, &dy);
1417 filterMotion(touchpad, &dx, &dy, time);
1419 touchpad->device->rel.dx = wl_fixed_from_double(dx);
1420 touchpad->device->rel.dy = wl_fixed_from_double(dy);
1421 touchpad->device->pending_events |= EVDEV_RELATIVE_MOTION;
1425 /// Notifier ///////////////////////////////////////////////////////////////
1428 WaylandEvdevInputEvent::notifyButton(struct evdev_input_device *device,
1429 uint32_t time, int32_t button,
1430 enum wl_pointer_button_state state)
1433 struct wl_seat *wlSeat = NULL;
1436 WaylandEvdevInputEvent *inputEvent = static_cast<WaylandEvdevInputEvent*>(device->master);
1440 wlSeat = inputEvent->inputDevice().seat();
1441 serial = wl_display_next_serial(inputEvent->inputDevice().display());
1443 if (state == WL_POINTER_BUTTON_STATE_PRESSED){
1444 if (wlSeat->pointer->button_count == 0){
1445 wlSeat->pointer->grab_button = button;
1446 wlSeat->pointer->grab_time = time;
1447 wlSeat->pointer->grab_x = wlSeat->pointer->x;
1448 wlSeat->pointer->grab_y = wlSeat->pointer->y;
1450 ++wlSeat->pointer->button_count;
1453 --wlSeat->pointer->button_count;
1455 wlEvent.x = wl_fixed_to_int(wlSeat->pointer->x);
1456 wlEvent.y = wl_fixed_to_int(wlSeat->pointer->y);
1457 wlEvent.buttonState = state;
1458 wlEvent.serial = serial;
1460 inputEvent->windowSystem().manageWLInputEvent(INPUT_DEVICE_POINTER,
1461 state == WL_POINTER_BUTTON_STATE_PRESSED ? INPUT_STATE_PRESSED :
1462 INPUT_STATE_RELEASED, &wlEvent);
1464 if (wlSeat->pointer->button_count == 1){
1465 wlSeat->pointer->grab_serial =
1466 wl_display_get_serial(inputEvent->inputDevice().display());
1471 WaylandEvdevInputEvent::notifyMotion(struct evdev_input_device *device,
1473 wl_fixed_t fx, wl_fixed_t fy)
1478 struct wl_seat *wlSeat = NULL;
1483 WaylandEvdevInputEvent *inputEvent = static_cast<WaylandEvdevInputEvent*>(device->master);
1487 wlSeat = inputEvent->inputDevice().seat();
1488 w = inputEvent->m_screenWidth;
1489 h = inputEvent->m_screenHeight;
1491 x = wl_fixed_to_int(fx);
1492 y = wl_fixed_to_int(fy);
1493 //old_x = wl_fixed_to_int(wlSeat->pointer->x);
1494 //old_y = wl_fixed_to_int(wlSeat->pointer->y);
1500 wlSeat->pointer->x = wl_fixed_from_int(x);
1501 wlSeat->pointer->y = wl_fixed_from_int(y);
1506 inputEvent->windowSystem().manageWLInputEvent(
1507 INPUT_DEVICE_POINTER, INPUT_STATE_MOTION, &wlEvent);
1511 WaylandEvdevInputEvent::notifyKey(struct evdev_input_device *device,
1512 uint32_t time, uint32_t key,
1513 enum wl_keyboard_key_state state,
1514 bool bUpdateAutomatic)
1516 WL_UNUSED(bUpdateAutomatic);
1519 struct wl_seat *wlSeat = NULL;
1522 WaylandEvdevInputEvent *inputEvent = static_cast<WaylandEvdevInputEvent*>(device->master);
1526 wlSeat = inputEvent->inputDevice().seat();
1527 if (state == WL_KEYBOARD_KEY_STATE_PRESSED){
1528 wlSeat->keyboard->grab_key = key;
1529 wlSeat->keyboard->grab_time = time;
1532 end = (uint32_t*)(((unsigned char*)wlSeat->keyboard->keys.data) + wlSeat->keyboard->keys.size);
1533 for (k = (uint32_t*)wlSeat->keyboard->keys.data; k < end; ++k){
1535 // Ignore server-generated repeats
1536 if (state == WL_KEYBOARD_KEY_STATE_PRESSED)
1541 wlSeat->keyboard->keys.size = end - (uint32_t*)wlSeat->keyboard->keys.data;
1542 if (state == WL_KEYBOARD_KEY_STATE_PRESSED){
1543 k = (uint32_t*)wl_array_add(&wlSeat->keyboard->keys, sizeof(*k));
1547 wlEvent.keyCode = key;
1548 wlEvent.keyState = state;
1550 inputEvent->windowSystem().manageWLInputEvent(INPUT_DEVICE_KEYBOARD,
1551 state == WL_KEYBOARD_KEY_STATE_PRESSED ? INPUT_STATE_PRESSED
1552 : INPUT_STATE_RELEASED, &wlEvent);
1556 WaylandEvdevInputEvent::notifyTouch(struct evdev_input_device *device)
1559 InputEventState eventState = INPUT_STATE_OTHER;
1561 WaylandEvdevInputEvent *inputEvent = static_cast<WaylandEvdevInputEvent*>(device->master);
1565 if (device->pending_events & EVDEV_ABSOLUTE_MT_DOWN){
1566 wlEvent.x = (int)wl_fixed_from_int(device->mt.x[device->mt.slot]);
1567 wlEvent.y = (int)wl_fixed_from_int(device->mt.y[device->mt.slot]);
1568 wlEvent.touchId = device->mt.slot;
1569 wlEvent.touchType = WL_TOUCH_DOWN;
1570 eventState = INPUT_STATE_PRESSED;
1572 if (device->pending_events & EVDEV_ABSOLUTE_MT_MOTION){
1573 wlEvent.x = (int)wl_fixed_from_int(device->mt.x[device->mt.slot]);
1574 wlEvent.y = (int)wl_fixed_from_int(device->mt.y[device->mt.slot]);
1575 wlEvent.touchId = device->mt.slot;
1576 wlEvent.touchType = WL_TOUCH_MOTION;
1577 eventState = INPUT_STATE_MOTION;
1579 if (device->pending_events & EVDEV_ABSOLUTE_MT_UP){
1582 wlEvent.touchId = device->mt.slot;
1583 wlEvent.touchType = WL_TOUCH_UP;
1584 eventState = INPUT_STATE_RELEASED;
1590 inputEvent->windowSystem().manageWLInputEvent(INPUT_DEVICE_TOUCH, eventState, &wlEvent);
1594 WaylandEvdevInputEvent::notifyModifiers(struct wl_seat *wlSeat, uint32_t serial)
1596 uint32_t mods_depressed, mods_latched, mods_locked, group;
1597 uint32_t mods_lookup;
1600 mods_depressed = xkb_state_serialize_mods(m_xkbState.state, (xkb_state_component)XKB_STATE_DEPRESSED);
1601 mods_latched = xkb_state_serialize_mods(m_xkbState.state, (xkb_state_component)XKB_STATE_LATCHED);
1602 mods_locked = xkb_state_serialize_mods(m_xkbState.state, (xkb_state_component)XKB_STATE_LOCKED);
1603 group = xkb_state_serialize_mods(m_xkbState.state, (xkb_state_component)XKB_STATE_EFFECTIVE);
1605 if (mods_depressed != wlSeat->keyboard->modifiers.mods_depressed ||
1606 mods_latched != wlSeat->keyboard->modifiers.mods_latched ||
1607 mods_locked != wlSeat->keyboard->modifiers.mods_locked ||
1608 group != wlSeat->keyboard->modifiers.group){
1612 wlSeat->keyboard->modifiers.mods_depressed = mods_depressed;
1613 wlSeat->keyboard->modifiers.mods_latched = mods_latched;
1614 wlSeat->keyboard->modifiers.mods_locked = mods_locked;
1615 wlSeat->keyboard->modifiers.group = group;
1617 // And update the modifier_state for bindings
1618 mods_lookup = mods_depressed | mods_latched;
1619 m_modifierState = 0;
1620 if (mods_lookup & (1 << m_xkbInfo.ctrl_mod)) m_modifierState |= MODIFIER_CTRL;
1621 if (mods_lookup & (1 << m_xkbInfo.alt_mod)) m_modifierState |= MODIFIER_ALT;
1622 if (mods_lookup & (1 << m_xkbInfo.super_mod)) m_modifierState |= MODIFIER_SUPER;
1623 if (mods_lookup & (1 << m_xkbInfo.shift_mod)) m_modifierState |= MODIFIER_SHIFT;
1626 m_inputDevice->sendModifiers(serial);