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 WL_UNUSED(A) (A)=(A)
45 static const char default_seat[] = "seat0";
47 // copied from udev/extras/input_id/input_id.c
48 // we must use this kernel-compatible implementation
49 #define BITS_PER_LONG (sizeof(unsigned long) * 8)
50 #define NBITS(x) ((((x)-1)/BITS_PER_LONG)+1)
51 #define OFF(x) ((x)%BITS_PER_LONG)
52 #define BIT(x) (1UL<<OFF(x))
53 #define LONG(x) ((x)/BITS_PER_LONG)
54 #define TEST_BIT(array, bit) ((array[LONG(bit)] >> OFF(bit)) & 1)
57 #define MAX_VELOCITY_DIFF 1.0
58 #define MOTION_TIMEOUT 300 // (ms)
59 #define NUM_POINTER_TRACKERS 16
61 struct evdev_dispatch_interface touchpad_interface = {
62 WaylandEvdevInputEvent::touchpadProcess,
63 WaylandEvdevInputEvent::touchpadDestroy,
66 struct evdev_dispatch_interface fallback_interface = {
67 WaylandEvdevInputEvent::fallbackProcess,
68 WaylandEvdevInputEvent::fallbackDestroy,
71 // Function prototypes
72 void acceleratorFilter (struct motion_filter *, struct motion_params *, void *, uint32_t);
73 void acceleratorDestroy(struct motion_filter *);
75 struct motion_filter_interface accelerator_interface = {
80 static struct touchpad_model_spec touchpad_spec_table[] = {
81 {0x0002, 0x0007, TOUCHPAD_MODEL_SYNAPTICS},
82 {0x0002, 0x0008, TOUCHPAD_MODEL_ALPS},
83 {0x05ac, 0x0000, TOUCHPAD_MODEL_APPLETOUCH},
84 {0x0002, 0x000e, TOUCHPAD_MODEL_ELANTECH},
85 {0x0000, 0x0000, TOUCHPAD_MODEL_UNKNOWN}
88 ////////////////////////////////////////////////////////////////////////////
91 isMotionEvent(struct input_event *e)
105 case ABS_MT_POSITION_X:
106 case ABS_MT_POSITION_Y:
114 static enum touchpad_model
115 getTouchpadModel(struct evdev_input_device *device)
120 if (ioctl(device->fd, EVIOCGID, &id) < 0)
121 return TOUCHPAD_MODEL_UNKNOWN;
123 for (i = 0; i < sizeof(touchpad_spec_table); ++i){
124 if (touchpad_spec_table[i].vendor == id.vendor &&
125 (!touchpad_spec_table[i].product ||
126 touchpad_spec_table[i].product == id.product)){
127 return touchpad_spec_table[i].model;
131 return TOUCHPAD_MODEL_UNKNOWN;
135 configureTouchpadPressure(struct touchpad_dispatch *touchpad,
136 int32_t pressure_min, int32_t pressure_max)
138 int32_t range = pressure_max - pressure_min + 1;
139 touchpad->has_pressure = 1;
141 // Magic numbers from xf86-input-synaptics
142 switch (touchpad->model){
143 case TOUCHPAD_MODEL_ELANTECH:
144 touchpad->pressure.touch_low = pressure_min + 1;
145 touchpad->pressure.touch_high = pressure_min + 1;
148 touchpad->pressure.touch_low = pressure_min + range * (25.0/256.0);
149 touchpad->pressure.touch_high = pressure_min + range * (30.0/256.0);
153 touchpad->pressure.press = pressure_min + range;
157 touchpadProfile(struct motion_filter *filter, void *data,
158 double velocity, uint32_t time)
162 struct touchpad_dispatch *touchpad = (struct touchpad_dispatch*)data;
165 accel_factor = velocity * touchpad->constant_accel_factor;
167 if (accel_factor > touchpad->max_accel_factor)
168 accel_factor = touchpad->max_accel_factor;
169 else if (accel_factor < touchpad->min_accel_factor)
170 accel_factor = touchpad->min_accel_factor;
175 static motion_filter*
176 createPointerAccelatorFilter(accel_profile_func_t profile)
178 struct pointer_accelerator *filter;
180 filter = (struct pointer_accelerator*)malloc(sizeof(*filter));
184 filter->base.interface = &accelerator_interface;
185 wl_list_init(&filter->base.link);
187 filter->profile = profile;
188 filter->last_velocity = 0.0;
192 filter->trackers = (struct pointer_tracker*)
193 calloc(NUM_POINTER_TRACKERS, sizeof(*filter->trackers));
194 filter->cur_tracker = 0;
196 return &filter->base;
199 static evdev_dispatch*
200 createFallbackDispatch()
202 struct evdev_dispatch *dispatch =
203 (struct evdev_dispatch*)malloc(sizeof(*dispatch));
204 if (dispatch == NULL)
207 dispatch->interface = &fallback_interface;
212 ////////////////////////////////////////////////////////////////////////
215 processTouch(struct evdev_input_device *device, struct input_event *e,
216 int screen_width, int screen_height)
220 device->mt.slot = e->value;
222 case ABS_MT_TRACKING_ID:
224 device->pending_events |= EVDEV_ABSOLUTE_MT_DOWN;
226 device->pending_events |= EVDEV_ABSOLUTE_MT_UP;
228 case ABS_MT_POSITION_X:
229 device->mt.x[device->mt.slot] =
230 (e->value - device->abs.min_x) * screen_width /
231 (device->abs.max_x - device->abs.min_x) +
232 0; //device->output->x;
233 device->pending_events |= EVDEV_ABSOLUTE_MT_MOTION;
235 case ABS_MT_POSITION_Y:
236 device->mt.y[device->mt.slot] =
237 (e->value - device->abs.min_y) * screen_height /
238 (device->abs.max_y - device->abs.min_y) +
239 0; //device->output->y;
240 device->pending_events |= EVDEV_ABSOLUTE_MT_MOTION;
246 processAbsoluteMotion(struct evdev_input_device *device, struct input_event *e,
247 int screen_width, int screen_height)
252 (e->value - device->abs.min_x) * screen_width /
253 (device->abs.max_x - device->abs.min_x) +
254 0; //device->output->x;
255 device->pending_events |= EVDEV_ABSOLUTE_MOTION;
259 (e->value - device->abs.min_y) * screen_height /
260 (device->abs.max_y - device->abs.min_y) +
261 0; //device->output->y;
262 device->abs.x = screen_width - device->abs.x;
263 device->pending_events |= EVDEV_ABSOLUTE_MOTION;
265 // The following is the effective code only from a specific model
268 device->abs.y = (e->value - device->abs.min_x) * screen_height /
269 (device->abs.max_x - device->abs.min_x);
270 device->pending_events |= EVDEV_ABSOLUTE_MOTION;
273 device->abs.x = (e->value - device->abs.min_y) * screen_width /
274 (device->abs.max_y - device->abs.min_y);
275 device->abs.x = screen_width - device->abs.x;
276 device->pending_events |= EVDEV_ABSOLUTE_MOTION;
282 ////////////////////////////////////////////////////////////////////////
285 hysteresis(int in, int center, int margin)
287 int diff = in - center;
288 if (abs(diff) <= margin)
292 return center + diff - margin;
293 else if (diff < -margin)
294 return center + diff + margin;
295 return center + diff;
298 static inline struct touchpad_motion*
299 motionHistoryOffset(struct touchpad_dispatch *touchpad, int offset)
302 (touchpad->motion_index - offset + TOUCHPAD_HISTORY_LENGTH) %
303 TOUCHPAD_HISTORY_LENGTH;
305 return &touchpad->motion_history[offsetIndex];
309 estimateDelta(int x0, int x1, int x2, int x3)
311 return (x0 + x1 - x2 - x3) / 4;
315 touchpadGetDelta(struct touchpad_dispatch *touchpad, double *dx, double *dy)
317 *dx = estimateDelta(motionHistoryOffset(touchpad, 0)->x,
318 motionHistoryOffset(touchpad, 1)->x,
319 motionHistoryOffset(touchpad, 2)->x,
320 motionHistoryOffset(touchpad, 3)->x);
321 *dy = estimateDelta(motionHistoryOffset(touchpad, 0)->y,
322 motionHistoryOffset(touchpad, 1)->y,
323 motionHistoryOffset(touchpad, 2)->y,
324 motionHistoryOffset(touchpad, 3)->y);
328 filterDispatch(struct motion_filter *filter, struct motion_params *motion,
329 void *data, uint32_t time)
331 filter->interface->filter(filter, motion, data, time);
335 filterMotion(struct touchpad_dispatch *touchpad,
336 double *dx, double *dy, uint32_t time)
338 struct motion_filter *filter;
339 struct motion_params motion;
344 wl_list_for_each(filter, &touchpad->motion_filters, link){
345 filterDispatch(filter, &motion, touchpad, time);
353 getDirection(int dx, int dy)
355 int dir = UNDEFINED_DIRECTION;
359 if (abs(dx) < 2 && abs(dy) < 2) {
360 if (dx > 0 && dy > 0)
362 else if (dx > 0 && dy < 0)
364 else if (dx < 0 && dy > 0)
366 else if (dx < 0 && dy < 0)
378 // Calculate r within the interval [0 to 8)
380 // r = [0 .. 2Ï€] where 0 is North
381 // d_f = r / 2Ï€ ([0 .. 1))
385 r = fmod(r + 2.5*M_PI, 2*M_PI);
388 // Mark one or two close enough octants
389 d1 = (int)(r + 0.9) % 8;
390 d2 = (int)(r + 0.1) % 8;
392 dir = (1 << d1) | (1 << d2);
399 feedTrackers(struct pointer_accelerator *accel,
400 double dx, double dy, uint32_t time)
403 struct pointer_tracker *trackers = accel->trackers;
405 for (i = 0; i < NUM_POINTER_TRACKERS; ++i){
406 trackers[i].dx += dx;
407 trackers[i].dy += dy;
410 current = (accel->cur_tracker + 1) % NUM_POINTER_TRACKERS;
411 accel->cur_tracker = current;
413 trackers[current].dx = 0.0;
414 trackers[current].dy = 0.0;
415 trackers[current].time = time;
416 trackers[current].dir = getDirection(dx, dy);
419 static struct pointer_tracker*
420 trackerByOffset(struct pointer_accelerator *accel, unsigned int offset)
423 (accel->cur_tracker + NUM_POINTER_TRACKERS - offset)
424 % NUM_POINTER_TRACKERS;
425 return &accel->trackers[index];
429 calculateTrackerVelocity(struct pointer_tracker *tracker, uint32_t time)
437 distance = sqrt(dx*dx + dy*dy);
438 return distance / (double)(time - tracker->time);
442 calculateVelocity(struct pointer_accelerator *accel, uint32_t time)
444 struct pointer_tracker *tracker;
447 double initial_velocity;
448 double velocity_diff;
451 unsigned int dir = trackerByOffset(accel, 0)->dir;
453 // Find first velocity
454 for (offset = 1; offset < NUM_POINTER_TRACKERS; offset++) {
455 tracker = trackerByOffset(accel, offset);
457 if (time <= tracker->time)
460 result = initial_velocity =
461 calculateTrackerVelocity(tracker, time);
462 if (initial_velocity > 0.0)
466 // Find least recent vector within a timelimit, maximum velocity diff
467 // and direction threshold.
468 for (; offset < NUM_POINTER_TRACKERS; offset++) {
469 tracker = trackerByOffset(accel, offset);
471 // Stop if too far away in time
472 if (time - tracker->time > MOTION_TIMEOUT ||
473 tracker->time > time)
476 // Stop if direction changed
481 velocity = calculateTrackerVelocity(tracker, time);
483 // Stop if velocity differs too much from initial
484 velocity_diff = fabs(initial_velocity - velocity);
485 if (velocity_diff > MAX_VELOCITY_DIFF)
495 accelerationProfile(struct pointer_accelerator *accel,
496 void *data, double velocity, uint32_t time)
498 return accel->profile(&accel->base, data, velocity, time);
502 calculateAcceleration(struct pointer_accelerator *accel,
503 void *data, double velocity, uint32_t time)
507 factor = accelerationProfile(accel, data, velocity, time);
508 factor += accelerationProfile(accel, data, accel->last_velocity, time);
510 accelerationProfile(accel, data,
511 (accel->last_velocity + velocity) / 2,
513 factor = factor / 6.0;
518 softenDelta(double lastDelta, double delta)
520 if (delta < -1.0 || delta > 1.0){
521 if (delta > lastDelta)
523 else if (delta < lastDelta)
530 applySoftening(struct pointer_accelerator *accel,
531 struct motion_params *motion)
533 motion->dx = softenDelta(accel->last_dx, motion->dx);
534 motion->dy = softenDelta(accel->last_dy, motion->dy);
538 acceleratorFilter(struct motion_filter *filter, struct motion_params *motion,
539 void *data, uint32_t time)
541 struct pointer_accelerator *accel = (struct pointer_accelerator*)filter;
545 feedTrackers(accel, motion->dx, motion->dy, time);
546 velocity = calculateVelocity(accel, time);
547 accel_value = calculateAcceleration(accel, data, velocity, time);
549 motion->dx = accel_value * motion->dx;
550 motion->dy = accel_value * motion->dy;
552 applySoftening(accel, motion);
554 accel->last_dx = motion->dx;
555 accel->last_dy = motion->dy;
557 accel->last_velocity = velocity;
561 acceleratorDestroy(struct motion_filter *filter)
563 struct pointer_accelerator *accel = (struct pointer_accelerator*)filter;
565 free(accel->trackers);
569 /// WaylandEvdevInputEvent /////////////////////////////////////////////////
571 WaylandEvdevInputEvent::WaylandEvdevInputEvent(WaylandBaseWindowSystem* windowSystem)
572 : WaylandInputEvent(windowSystem)
577 wl_list_init(&m_deviceList);
580 WaylandEvdevInputEvent::~WaylandEvdevInputEvent()
586 struct evdev_input_device *device, *next;
588 wl_list_for_each_safe(device, next, &m_deviceList, link){
589 removeDevice(device);
594 WaylandEvdevInputEvent::removeDevice(struct evdev_input_device *device)
596 struct evdev_dispatch *dispatch = device->dispatch;
599 dispatch->interface->destroy(dispatch);
601 wl_event_source_remove(device->source);
602 wl_list_remove(&device->link);
604 mtdev_close_delete(device->mtdev);
606 free(device->devnode);
611 WaylandEvdevInputEvent::setupInputEvent()
613 LOG_INFO("WaylandEvdevInputEvent", "setupInputEvent IN");
615 WaylandInputEvent::setupInputEvent();
617 m_screenWidth = m_windowSystem->getWindowWidth();
618 m_screenHeight = m_windowSystem->getWindowHeight();
621 bool bRet = addDevices();
627 LOG_INFO("WaylandEvdevInputEvent", "setupInputEvent OUT");
631 WaylandEvdevInputEvent::addDevices()
636 LOG_ERROR("WaylandEvdevInputEvent", "Failed to initialize udev context");
640 struct udev_enumerate *e = udev_enumerate_new(m_udev);
641 udev_enumerate_add_match_subsystem(e, "input");
642 udev_enumerate_scan_devices(e);
644 struct udev_list_entry *entry;
645 const char *path, *sysname;
646 struct udev_device *device;
647 udev_list_entry_foreach(entry, udev_enumerate_get_list_entry(e)){
648 path = udev_list_entry_get_name(entry);
649 device = udev_device_new_from_syspath(m_udev, path);
651 sysname = udev_device_get_sysname(device);
652 if (strncmp("event", sysname, 5) != 0){
653 udev_device_unref(device);
658 udev_device_unref(device);
660 udev_enumerate_unref(e);
662 notifyKeyboardFocus();
664 if (wl_list_empty(&m_deviceList)){
665 LOG_WARNING("WaylandEvdevInputEvent", "No input devices on entering service");
672 WaylandEvdevInputEvent::addDevice(struct udev_device *udevDevice)
675 const char *device_seat;
677 device_seat = udev_device_get_property_value(udevDevice, "ID_SEAT");
679 device_seat = default_seat;
681 devnode = udev_device_get_devnode(udevDevice);
682 createInputDevice(m_windowSystem->getNativeDisplayHandle(), devnode);
686 WaylandEvdevInputEvent::createInputDevice(struct wl_display *display, const char *path)
688 struct evdev_input_device *device;
689 struct wl_event_loop *eventLoop;
691 device = (struct evdev_input_device*)malloc(sizeof(*device));
696 device->master = this;
698 device->mtdev = NULL;
699 device->devnode = strdup(path);
700 device->mt.slot = -1;
703 device->dispatch = NULL;
705 device->fd = open(path, O_RDWR | O_NONBLOCK);
710 if (configureDevice(device) < 0){
714 // If the dispatch was not set up use the fallback
715 if (device->dispatch == NULL)
716 device->dispatch = createFallbackDispatch();
717 if (device->dispatch == NULL)
721 device->mtdev = mtdev_new_open(device->fd);
723 LOG_WARNING("WaylandEvdevInputEvent", "mtdev failed to open for " << path);
727 eventLoop = wl_display_get_event_loop(display);
728 device->source = wl_event_loop_add_fd(eventLoop, device->fd, WL_EVENT_READABLE,
729 WaylandEvdevInputEvent::handleInputEvent,
731 if (device->source == NULL){
735 wl_list_insert(m_deviceList.prev, &(device->link));
740 device->dispatch->interface->destroy(device->dispatch);
744 free(device->devnode);
750 WaylandEvdevInputEvent::configureDevice(struct evdev_input_device *device)
752 struct input_absinfo absinfo;
753 unsigned long ev_bits[NBITS(EV_MAX)];
754 unsigned long abs_bits[NBITS(ABS_MAX)];
755 unsigned long rel_bits[NBITS(ABS_MAX)];
756 unsigned long key_bits[NBITS(KEY_MAX)];
763 ioctl(device->fd, EVIOCGBIT(0, sizeof(ev_bits)), ev_bits);
764 if (TEST_BIT(ev_bits, EV_ABS)){
767 ioctl(device->fd, EVIOCGBIT(EV_ABS, sizeof(abs_bits)), abs_bits);
768 if (TEST_BIT(abs_bits, ABS_X)){
769 ioctl(device->fd, EVIOCGABS(ABS_X), &absinfo);
770 device->abs.min_x = absinfo.minimum;
771 device->abs.max_x = absinfo.maximum;
772 device->caps |= EVDEV_MOTION_ABS;
774 if (TEST_BIT(abs_bits, ABS_Y)){
775 ioctl(device->fd, EVIOCGABS(ABS_Y), &absinfo);
776 device->abs.min_y = absinfo.minimum;
777 device->abs.max_y = absinfo.maximum;
778 device->caps |= EVDEV_MOTION_ABS;
780 if (TEST_BIT(abs_bits, ABS_MT_SLOT)){
783 device->caps |= EVDEV_TOUCH;
786 if (TEST_BIT(ev_bits, EV_REL)){
787 ioctl(device->fd, EVIOCGBIT(EV_REL, sizeof(rel_bits)), rel_bits);
788 if (TEST_BIT(rel_bits, REL_X) || TEST_BIT(rel_bits, REL_Y)){
789 device->caps |= EVDEV_MOTION_REL;
792 if (TEST_BIT(ev_bits, EV_KEY)){
794 ioctl(device->fd, EVIOCGBIT(EV_KEY, sizeof(key_bits)), key_bits);
795 if (TEST_BIT(key_bits, BTN_TOOL_FINGER) &&
796 !TEST_BIT(key_bits, BTN_TOOL_PEN) && hasAbs){
797 device->dispatch = createTouchpad(device);
800 for (i = KEY_ESC; i < KEY_MAX; ++i){
801 if (i >= BTN_MISC && i < KEY_OK)
803 if (TEST_BIT(key_bits, i)){
804 device->caps |= EVDEV_KEYBOARD;
808 for (i = BTN_MISC; i < KEY_OK; ++i){
809 if (TEST_BIT(key_bits, i)){
810 device->caps |= EVDEV_BUTTON;
815 if (TEST_BIT(ev_bits, EV_LED)){
816 device->caps |= EVDEV_KEYBOARD;
819 // This rule tries to catch accelerometer devices and opt out. We may
820 // want to adjust the protocol later adding a proper event for dealing
821 // with accelerometers and implement here accordingly
822 if (hasAbs && !hasKey && !device->isMt)
826 fprintf(stdout, "DEVICE: [%s] information\n", device->devnode);
827 fprintf(stdout, " capabilities: EVDEV_KEYBOARD %s\n"
829 " EVDEV_MOTION_ABS %s\n"
830 " EVDEV_MOTION_REL %s\n"
832 (device->caps & EVDEV_KEYBOARD) ? "TRUE" : "FALSE",
833 (device->caps & EVDEV_BUTTON) ? "TRUE" : "FALSE",
834 (device->caps & EVDEV_MOTION_ABS) ? "TRUE" : "FALSE",
835 (device->caps & EVDEV_MOTION_REL) ? "TRUE" : "FALSE",
836 (device->caps & EVDEV_TOUCH) ? "TRUE" : "FALSE");
837 if (device->caps & EVDEV_MOTION_ABS){
838 fprintf(stdout, " abs: min_x(%4d), min_y(%4d)\n", device->abs.min_x, device->abs.min_y);
839 fprintf(stdout, " max_x(%4d), max_y(%4d)\n", device->abs.max_x, device->abs.max_y);
840 fprintf(stdout, " x(%4d), y(%4d)\n", device->abs.x, device->abs.y);
842 fprintf(stdout, "\n");
845 if ((device->caps & (EVDEV_MOTION_ABS | EVDEV_MOTION_REL | EVDEV_BUTTON))){
848 if ((device->caps & (EVDEV_KEYBOARD))){
849 initKeyboardDevice(NULL);
851 if ((device->caps & (EVDEV_TOUCH))){
859 WaylandEvdevInputEvent::notifyKeyboardFocus()
861 struct evdev_input_device *device;
862 struct wl_array keys;
863 char evdev_keys[(KEY_CNT + 7) / 8], all_keys[(KEY_CNT + 7) / 8];
868 memset(all_keys, 0, sizeof(all_keys));
869 wl_list_for_each(device, &m_deviceList, link){
870 memset(evdev_keys, 0, sizeof(evdev_keys));
871 ret = ioctl(device->fd, EVIOCGKEY(sizeof(evdev_keys)), evdev_keys);
873 LOG_WARNING("WaylandEvdevInputEvent", "Failed to get keys for device: " <<
877 for (i = 0; i < ARRAY_LENGTH(evdev_keys); ++i){
878 all_keys[i] |= evdev_keys[i];
882 wl_array_init(&keys);
883 for (i = 0; i < KEY_CNT; ++i){
884 set = all_keys[i >> 3] & (1 << (i & 7));
886 k = (uint32_t*)wl_array_add(&keys, sizeof(*k));
891 notifyKeyboardFocusIn(&keys, STATE_UPDATE_AUTOMATIC);
893 wl_array_release(&keys);
897 WaylandEvdevInputEvent::notifyKeyboardFocusIn(struct wl_array *keys,
898 enum key_state_update updateState)
900 struct wl_seat *wlSeat;
903 if ((wlSeat = m_inputDevice->seat()) == NULL){
906 serial = wl_display_next_serial(m_inputDevice->display());
907 wl_array_copy(&wlSeat->keyboard->keys, keys);
909 struct wl_array *array = &wlSeat->keyboard->keys;
910 for (k = (uint32_t*)array->data;
911 (const char*)k < (const char*)array->data + array->size;
913 if (updateState == STATE_UPDATE_AUTOMATIC){
914 updateModifierState(wlSeat, serial, *k, WL_KEYBOARD_KEY_STATE_PRESSED);
920 WaylandEvdevInputEvent::updateModifierState(struct wl_seat *wlSeat, uint32_t serial,
921 uint32_t key, enum wl_keyboard_key_state state)
923 enum xkb_key_direction direction;
925 if (state == WL_KEYBOARD_KEY_STATE_PRESSED)
926 direction = XKB_KEY_DOWN;
928 direction = XKB_KEY_UP;
930 // Offset the keycode by 8, as the evdev XKB rules reflect X's
931 // broken keycode system, which starts at 8.
932 xkb_state_update_key(m_xkbState.state, key + 8, direction);
934 notifyModifiers(wlSeat, serial);
937 struct evdev_dispatch*
938 WaylandEvdevInputEvent::createTouchpad(struct evdev_input_device *device)
940 struct touchpad_dispatch *touchpad;
942 touchpad = (struct touchpad_dispatch*)malloc(sizeof(*touchpad));
943 if (touchpad == NULL)
946 touchpad->base.interface = &touchpad_interface;
948 touchpad->device = device;
949 wl_list_init(&touchpad->motion_filters);
951 configureTouchpad(touchpad, device);
953 return &touchpad->base;
957 WaylandEvdevInputEvent::configureTouchpad(struct touchpad_dispatch *touchpad,
958 struct evdev_input_device *device)
960 struct motion_filter *accel;
962 struct input_absinfo absinfo;
963 unsigned long abs_bits[NBITS(ABS_MAX)];
970 touchpad->model = getTouchpadModel(device);
972 // Configure pressure
973 ioctl(device->fd, EVIOCGBIT(EV_ABS, sizeof(abs_bits)), abs_bits);
974 if (TEST_BIT(abs_bits, ABS_PRESSURE)) {
975 ioctl(device->fd, EVIOCGABS(ABS_PRESSURE), &absinfo);
976 configureTouchpadPressure(touchpad,
981 // Configure acceleration factor
982 width = abs(device->abs.max_x - device->abs.min_x);
983 height = abs(device->abs.max_y - device->abs.min_y);
984 diagonal = sqrt(width*width + height*height);
986 touchpad->constant_accel_factor =
987 DEFAULT_CONSTANT_ACCEL_NUMERATOR / diagonal;
989 touchpad->min_accel_factor = DEFAULT_MIN_ACCEL_FACTOR;
990 touchpad->max_accel_factor = DEFAULT_MAX_ACCEL_FACTOR;
992 touchpad->hysteresis.margin_x = diagonal / DEFAULT_HYSTERESIS_MARGIN_DENOMINATOR;
993 touchpad->hysteresis.margin_y = diagonal / DEFAULT_HYSTERESIS_MARGIN_DENOMINATOR;
994 touchpad->hysteresis.center_x = 0;
995 touchpad->hysteresis.center_y = 0;
997 // Configure acceleration profile
998 accel = createPointerAccelatorFilter(touchpadProfile);
999 wl_list_insert(&touchpad->motion_filters, &accel->link);
1001 // Setup initial state
1002 touchpad->reset = 1;
1004 memset(touchpad->motion_history, 0, sizeof touchpad->motion_history);
1005 touchpad->motion_index = 0;
1006 touchpad->motion_count = 0;
1008 touchpad->state = TOUCHPAD_STATE_NONE;
1009 touchpad->last_finger_state = 0;
1010 touchpad->finger_state = 0;
1014 WaylandEvdevInputEvent::handleInputEvent(int fd, uint32_t mask, void *data)
1018 struct evdev_input_device *device = (evdev_input_device*)data;
1019 struct input_event ev[32];
1023 len = mtdev_get(device->mtdev, fd, ev,
1024 ARRAY_LENGTH(ev)) * sizeof(struct input_event);
1027 len = read(fd, &ev, sizeof(ev));
1030 if (len < 0 || len % sizeof(ev[0]) != 0){
1034 WaylandEvdevInputEvent::processEvents(device, ev, len / sizeof(ev[0]));
1042 WaylandEvdevInputEvent::processEvents(struct evdev_input_device *device,
1043 struct input_event *ev,
1046 struct evdev_dispatch *dispatch = device->dispatch;
1047 struct input_event *e, *end;
1050 device->pending_events = 0;
1054 for (; e < end; ++e){
1055 time = e->time.tv_sec * 1000 + e->time.tv_usec / 1000;
1057 if (!isMotionEvent(e)){
1058 WaylandEvdevInputEvent::flushMotion(device, time);
1061 dispatch->interface->process(dispatch, device, e, time);
1064 WaylandEvdevInputEvent::flushMotion(device, time);
1068 WaylandEvdevInputEvent::flushMotion(struct evdev_input_device *device,
1071 if (!device->pending_events)
1074 WaylandEvdevInputEvent *inputEvent = static_cast<WaylandEvdevInputEvent*>(device->master);
1078 if (device->pending_events & EVDEV_RELATIVE_MOTION){
1079 struct wl_seat *wlSeat = inputEvent->inputDevice().seat();
1082 notifyMotion(device, time,
1083 wlSeat->pointer->x + device->rel.dx,
1084 wlSeat->pointer->y + device->rel.dy);
1086 device->pending_events &= ~EVDEV_RELATIVE_MOTION;
1090 if (device->pending_events & EVDEV_ABSOLUTE_MT_DOWN){
1092 notifyTouch(device);
1093 device->pending_events &= ~EVDEV_ABSOLUTE_MT_DOWN;
1094 device->pending_events &= ~EVDEV_ABSOLUTE_MT_MOTION;
1096 if (device->pending_events & EVDEV_ABSOLUTE_MT_MOTION){
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_UP){
1104 notifyTouch(device);
1105 device->pending_events &= ~EVDEV_ABSOLUTE_MT_UP;
1107 if (device->pending_events & EVDEV_ABSOLUTE_MOTION){
1109 notifyMotion(device, time,
1110 wl_fixed_from_int(device->abs.x),
1111 wl_fixed_from_int(device->abs.y));
1112 device->pending_events &= ~EVDEV_ABSOLUTE_MOTION;
1116 /// Default event handler //////////////////////////////////////////////////
1119 WaylandEvdevInputEvent::fallbackProcess(struct evdev_dispatch *dispatch,
1120 struct evdev_input_device *device,
1121 struct input_event *e,
1124 WL_UNUSED(dispatch);
1128 evdevProcessRelative(device, time, e);
1131 evdevProcessAbsolute(device, e);
1134 evdevProcessKey(device, time, e);
1140 WaylandEvdevInputEvent::fallbackDestroy(struct evdev_dispatch *dispatch)
1142 if (dispatch) free(dispatch);
1146 WaylandEvdevInputEvent::evdevProcessRelative(struct evdev_input_device *device,
1147 uint32_t /*time*/, struct input_event *e)
1151 device->rel.dx += wl_fixed_from_int(e->value);
1152 device->pending_events |= EVDEV_RELATIVE_MOTION;
1155 device->rel.dy += wl_fixed_from_int(e->value);
1156 device->pending_events |= EVDEV_RELATIVE_MOTION;
1166 WaylandEvdevInputEvent::evdevProcessAbsolute(struct evdev_input_device *device,
1167 struct input_event *e)
1169 WaylandEvdevInputEvent *inputEvent = static_cast<WaylandEvdevInputEvent*>(device->master);
1173 int w = inputEvent->m_screenWidth;
1174 int h = inputEvent->m_screenHeight;
1177 processTouch(device, e, w, h);
1179 processAbsoluteMotion(device, e, w, h);
1184 WaylandEvdevInputEvent::evdevProcessKey(struct evdev_input_device *device,
1185 uint32_t time, struct input_event *e)
1201 notifyButton(device, time, e->code,
1202 e->value ? WL_POINTER_BUTTON_STATE_PRESSED
1203 : WL_POINTER_BUTTON_STATE_RELEASED);
1207 notifyKey(device, time, e->code,
1208 e->value ? WL_KEYBOARD_KEY_STATE_PRESSED
1209 : WL_KEYBOARD_KEY_STATE_RELEASED,
1215 /// Multi-touch event handler //////////////////////////////////////////////
1218 WaylandEvdevInputEvent::touchpadProcess(struct evdev_dispatch *dispatch,
1219 struct evdev_input_device *device,
1220 struct input_event *e,
1223 struct touchpad_dispatch *touchpad = (struct touchpad_dispatch*)dispatch;
1227 if (e->code == SYN_REPORT)
1228 touchpad->event_mask |= TOUCHPAD_EVENT_REPORT;
1231 touchpadProcessAbsolute(touchpad, device, e);
1234 touchpadProcessKey(touchpad, device, e, time);
1238 touchpadUpdateState(touchpad, time);
1242 WaylandEvdevInputEvent::touchpadDestroy(struct evdev_dispatch *dispatch)
1244 struct touchpad_dispatch *touchpad = (struct touchpad_dispatch*)dispatch;
1245 struct motion_filter *filter;
1246 struct motion_filter *next;
1248 wl_list_for_each_safe(filter, next, &touchpad->motion_filters, link){
1249 filter->interface->destroy(filter);
1252 if (dispatch) free(dispatch);
1256 WaylandEvdevInputEvent::touchpadProcessAbsolute(struct touchpad_dispatch *touchpad,
1257 struct evdev_input_device *device,
1258 struct input_event *e)
1264 if (e->value > touchpad->pressure.press)
1265 touchpad->state = TOUCHPAD_STATE_PRESS;
1266 else if (e->value > touchpad->pressure.touch_high)
1267 touchpad->state = TOUCHPAD_STATE_TOUCH;
1268 else if (e->value < touchpad->pressure.touch_low){
1269 if (touchpad->state > TOUCHPAD_STATE_NONE)
1270 touchpad->reset = 1;
1271 touchpad->state = TOUCHPAD_STATE_NONE;
1275 if (touchpad->state >= TOUCHPAD_STATE_TOUCH){
1276 touchpad->hw_abs.x = e->value;
1277 touchpad->event_mask |= TOUCHPAD_EVENT_ABSOLUTE_ANY;
1278 touchpad->event_mask |= TOUCHPAD_EVENT_ABSOLUTE_X;
1282 if (touchpad->state >= TOUCHPAD_STATE_TOUCH){
1283 touchpad->hw_abs.y = e->value;
1284 touchpad->event_mask |= TOUCHPAD_EVENT_ABSOLUTE_ANY;
1285 touchpad->event_mask |= TOUCHPAD_EVENT_ABSOLUTE_Y;
1292 WaylandEvdevInputEvent::touchpadProcessKey(struct touchpad_dispatch *touchpad,
1293 struct evdev_input_device * device,
1294 struct input_event *e,
1299 if (!touchpad->has_pressure){
1301 touchpad->state = TOUCHPAD_STATE_NONE;
1302 touchpad->reset = 1;
1305 touchpad->state = e->value ? TOUCHPAD_STATE_TOUCH
1306 : TOUCHPAD_STATE_NONE;
1319 notifyButton(device, time, e->code,
1320 e->value ? WL_POINTER_BUTTON_STATE_PRESSED
1321 : WL_POINTER_BUTTON_STATE_RELEASED);
1324 case BTN_TOOL_RUBBER:
1325 case BTN_TOOL_BRUSH:
1326 case BTN_TOOL_PENCIL:
1327 case BTN_TOOL_AIRBRUSH:
1328 case BTN_TOOL_MOUSE:
1330 touchpad->reset = 1;
1332 case BTN_TOOL_FINGER:
1333 touchpad->finger_state =
1334 ~TOUCHPAD_FINGERS_ONE | e->value ? TOUCHPAD_FINGERS_ONE : 0;
1336 case BTN_TOOL_DOUBLETAP:
1337 touchpad->finger_state =
1338 ~TOUCHPAD_FINGERS_TWO | e->value ? TOUCHPAD_FINGERS_TWO : 0;
1340 case BTN_TOOL_TRIPLETAP:
1341 touchpad->finger_state =
1342 ~TOUCHPAD_FINGERS_THREE | e->value ? TOUCHPAD_FINGERS_THREE : 0;
1348 WaylandEvdevInputEvent::touchpadUpdateState(struct touchpad_dispatch *touchpad,
1352 int center_x, center_y;
1355 if (touchpad->reset ||
1356 touchpad->last_finger_state != touchpad->finger_state) {
1357 touchpad->reset = 0;
1358 touchpad->motion_count = 0;
1359 touchpad->event_mask = TOUCHPAD_EVENT_NONE;
1360 touchpad->event_mask_filter =
1361 TOUCHPAD_EVENT_ABSOLUTE_X | TOUCHPAD_EVENT_ABSOLUTE_Y;
1363 touchpad->last_finger_state = touchpad->finger_state;
1367 touchpad->last_finger_state = touchpad->finger_state;
1369 if (!(touchpad->event_mask & TOUCHPAD_EVENT_REPORT))
1372 touchpad->event_mask &= ~TOUCHPAD_EVENT_REPORT;
1374 if ((touchpad->event_mask & touchpad->event_mask_filter) !=
1375 touchpad->event_mask_filter)
1378 touchpad->event_mask_filter = TOUCHPAD_EVENT_ABSOLUTE_ANY;
1379 touchpad->event_mask = 0;
1381 // Avoid noice by moving center only when delta reaches a threshold
1382 // distance from the old center
1383 if (touchpad->motion_count > 0) {
1384 center_x = hysteresis(touchpad->hw_abs.x,
1385 touchpad->hysteresis.center_x,
1386 touchpad->hysteresis.margin_x);
1387 center_y = hysteresis(touchpad->hw_abs.y,
1388 touchpad->hysteresis.center_y,
1389 touchpad->hysteresis.margin_y);
1392 center_x = touchpad->hw_abs.x;
1393 center_y = touchpad->hw_abs.y;
1395 touchpad->hysteresis.center_x = center_x;
1396 touchpad->hysteresis.center_y = center_y;
1397 touchpad->hw_abs.x = center_x;
1398 touchpad->hw_abs.y = center_y;
1400 // Update motion history tracker
1401 motion_index = (touchpad->motion_index + 1) % TOUCHPAD_HISTORY_LENGTH;
1402 touchpad->motion_index = motion_index;
1403 touchpad->motion_history[motion_index].x = touchpad->hw_abs.x;
1404 touchpad->motion_history[motion_index].y = touchpad->hw_abs.y;
1405 if (touchpad->motion_count < 4)
1406 touchpad->motion_count++;
1408 if (touchpad->motion_count >= 4) {
1409 touchpadGetDelta(touchpad, &dx, &dy);
1411 filterMotion(touchpad, &dx, &dy, time);
1413 touchpad->device->rel.dx = wl_fixed_from_double(dx);
1414 touchpad->device->rel.dy = wl_fixed_from_double(dy);
1415 touchpad->device->pending_events |= EVDEV_RELATIVE_MOTION;
1419 /// Notifier ///////////////////////////////////////////////////////////////
1422 WaylandEvdevInputEvent::notifyButton(struct evdev_input_device *device,
1423 uint32_t time, int32_t button,
1424 enum wl_pointer_button_state state)
1427 struct wl_seat *wlSeat = NULL;
1430 WaylandEvdevInputEvent *inputEvent = static_cast<WaylandEvdevInputEvent*>(device->master);
1434 wlSeat = inputEvent->inputDevice().seat();
1435 serial = wl_display_next_serial(inputEvent->inputDevice().display());
1437 if (state == WL_POINTER_BUTTON_STATE_PRESSED){
1438 if (wlSeat->pointer->button_count == 0){
1439 wlSeat->pointer->grab_button = button;
1440 wlSeat->pointer->grab_time = time;
1441 wlSeat->pointer->grab_x = wlSeat->pointer->x;
1442 wlSeat->pointer->grab_y = wlSeat->pointer->y;
1444 ++wlSeat->pointer->button_count;
1447 --wlSeat->pointer->button_count;
1449 wlEvent.x = wl_fixed_to_int(wlSeat->pointer->x);
1450 wlEvent.y = wl_fixed_to_int(wlSeat->pointer->y);
1451 wlEvent.buttonState = state;
1452 wlEvent.serial = serial;
1454 inputEvent->windowSystem().manageWLInputEvent(INPUT_DEVICE_POINTER,
1455 state == WL_POINTER_BUTTON_STATE_PRESSED ? INPUT_STATE_PRESSED :
1456 INPUT_STATE_RELEASED, &wlEvent);
1458 if (wlSeat->pointer->button_count == 1){
1459 wlSeat->pointer->grab_serial =
1460 wl_display_get_serial(inputEvent->inputDevice().display());
1465 WaylandEvdevInputEvent::notifyMotion(struct evdev_input_device *device,
1467 wl_fixed_t fx, wl_fixed_t fy)
1472 struct wl_seat *wlSeat = NULL;
1477 WaylandEvdevInputEvent *inputEvent = static_cast<WaylandEvdevInputEvent*>(device->master);
1481 wlSeat = inputEvent->inputDevice().seat();
1482 w = inputEvent->m_screenWidth;
1483 h = inputEvent->m_screenHeight;
1485 x = wl_fixed_to_int(fx);
1486 y = wl_fixed_to_int(fy);
1487 //old_x = wl_fixed_to_int(wlSeat->pointer->x);
1488 //old_y = wl_fixed_to_int(wlSeat->pointer->y);
1494 wlSeat->pointer->x = wl_fixed_from_int(x);
1495 wlSeat->pointer->y = wl_fixed_from_int(y);
1500 inputEvent->windowSystem().manageWLInputEvent(
1501 INPUT_DEVICE_POINTER, INPUT_STATE_MOTION, &wlEvent);
1505 WaylandEvdevInputEvent::notifyKey(struct evdev_input_device *device,
1506 uint32_t time, uint32_t key,
1507 enum wl_keyboard_key_state state,
1508 bool bUpdateAutomatic)
1510 WL_UNUSED(bUpdateAutomatic);
1513 struct wl_seat *wlSeat = NULL;
1516 WaylandEvdevInputEvent *inputEvent = static_cast<WaylandEvdevInputEvent*>(device->master);
1520 wlSeat = inputEvent->inputDevice().seat();
1521 if (state == WL_KEYBOARD_KEY_STATE_PRESSED){
1522 wlSeat->keyboard->grab_key = key;
1523 wlSeat->keyboard->grab_time = time;
1526 end = (uint32_t*)(((unsigned char*)wlSeat->keyboard->keys.data) + wlSeat->keyboard->keys.size);
1527 for (k = (uint32_t*)wlSeat->keyboard->keys.data; k < end; ++k){
1529 // Ignore server-generated repeats
1530 if (state == WL_KEYBOARD_KEY_STATE_PRESSED)
1535 wlSeat->keyboard->keys.size = end - (uint32_t*)wlSeat->keyboard->keys.data;
1536 if (state == WL_KEYBOARD_KEY_STATE_PRESSED){
1537 k = (uint32_t*)wl_array_add(&wlSeat->keyboard->keys, sizeof(*k));
1541 wlEvent.keyCode = key;
1542 wlEvent.keyState = state;
1544 inputEvent->windowSystem().manageWLInputEvent(INPUT_DEVICE_KEYBOARD,
1545 state == WL_KEYBOARD_KEY_STATE_PRESSED ? INPUT_STATE_PRESSED
1546 : INPUT_STATE_RELEASED, &wlEvent);
1550 WaylandEvdevInputEvent::notifyTouch(struct evdev_input_device *device)
1553 InputEventState eventState = INPUT_STATE_OTHER;
1555 WaylandEvdevInputEvent *inputEvent = static_cast<WaylandEvdevInputEvent*>(device->master);
1559 if (device->pending_events & EVDEV_ABSOLUTE_MT_DOWN){
1560 wlEvent.x = (int)wl_fixed_from_int(device->mt.x[device->mt.slot]);
1561 wlEvent.y = (int)wl_fixed_from_int(device->mt.y[device->mt.slot]);
1562 wlEvent.touchId = device->mt.slot;
1563 wlEvent.touchType = WL_TOUCH_DOWN;
1564 eventState = INPUT_STATE_PRESSED;
1566 if (device->pending_events & EVDEV_ABSOLUTE_MT_MOTION){
1567 wlEvent.x = (int)wl_fixed_from_int(device->mt.x[device->mt.slot]);
1568 wlEvent.y = (int)wl_fixed_from_int(device->mt.y[device->mt.slot]);
1569 wlEvent.touchId = device->mt.slot;
1570 wlEvent.touchType = WL_TOUCH_MOTION;
1571 eventState = INPUT_STATE_MOTION;
1573 if (device->pending_events & EVDEV_ABSOLUTE_MT_UP){
1576 wlEvent.touchId = device->mt.slot;
1577 wlEvent.touchType = WL_TOUCH_UP;
1578 eventState = INPUT_STATE_RELEASED;
1584 inputEvent->windowSystem().manageWLInputEvent(INPUT_DEVICE_TOUCH, eventState, &wlEvent);
1588 WaylandEvdevInputEvent::notifyModifiers(struct wl_seat *wlSeat, uint32_t serial)
1590 uint32_t mods_depressed, mods_latched, mods_locked, group;
1591 uint32_t mods_lookup;
1594 mods_depressed = xkb_state_serialize_mods(m_xkbState.state, XKB_STATE_DEPRESSED);
1595 mods_latched = xkb_state_serialize_mods(m_xkbState.state, XKB_STATE_LATCHED);
1596 mods_locked = xkb_state_serialize_mods(m_xkbState.state, XKB_STATE_LOCKED);
1597 group = xkb_state_serialize_mods(m_xkbState.state, XKB_STATE_EFFECTIVE);
1599 if (mods_depressed != wlSeat->keyboard->modifiers.mods_depressed ||
1600 mods_latched != wlSeat->keyboard->modifiers.mods_latched ||
1601 mods_locked != wlSeat->keyboard->modifiers.mods_locked ||
1602 group != wlSeat->keyboard->modifiers.group){
1606 wlSeat->keyboard->modifiers.mods_depressed = mods_depressed;
1607 wlSeat->keyboard->modifiers.mods_latched = mods_latched;
1608 wlSeat->keyboard->modifiers.mods_locked = mods_locked;
1609 wlSeat->keyboard->modifiers.group = group;
1611 // And update the modifier_state for bindings
1612 mods_lookup = mods_depressed | mods_latched;
1613 m_modifierState = 0;
1614 if (mods_lookup & (1 << m_xkbInfo.ctrl_mod)) m_modifierState |= MODIFIER_CTRL;
1615 if (mods_lookup & (1 << m_xkbInfo.alt_mod)) m_modifierState |= MODIFIER_ALT;
1616 if (mods_lookup & (1 << m_xkbInfo.super_mod)) m_modifierState |= MODIFIER_SUPER;
1617 if (mods_lookup & (1 << m_xkbInfo.shift_mod)) m_modifierState |= MODIFIER_SHIFT;
1620 m_inputDevice->sendModifiers(serial);