Fixed bug 4665 - Add support for single touch evdev devices
authorSam Lantinga <slouken@libsdl.org>
Wed, 12 Jun 2019 07:55:48 -0700
changeset 128455b0bc0ed588a
parent 12844 d92b5fbb5ac0
child 12846 c54ce7eddcbe
Fixed bug 4665 - Add support for single touch evdev devices

Jan Martin Mikkelsen

The attached patch adds support for single-touch evdev devices.

These devices report ABS_X, ABS_Y and BTN_TOUCH events. This patch sets them up as MT devices with a single slot and handles the appropriate messages.
src/core/linux/SDL_evdev.c
     1.1 --- a/src/core/linux/SDL_evdev.c	Wed Jun 12 00:55:05 2019 +0200
     1.2 +++ b/src/core/linux/SDL_evdev.c	Wed Jun 12 07:55:48 2019 -0700
     1.3 @@ -272,6 +272,12 @@
     1.4                         position is sent in EV_ABS ABS_X/ABS_Y, switching to
     1.5                         next finger after earlist is released) */
     1.6                      if (item->is_touchscreen && events[i].code == BTN_TOUCH) {
     1.7 +                        if (item->touchscreen_data->max_slots == 1) {
     1.8 +                            if (events[i].value)
     1.9 +                                item->touchscreen_data->slots[0].delta = EVDEV_TOUCH_SLOTDELTA_DOWN;
    1.10 +                            else
    1.11 +                                item->touchscreen_data->slots[0].delta = EVDEV_TOUCH_SLOTDELTA_UP;
    1.12 +                        }
    1.13                          break;
    1.14                      }
    1.15  
    1.16 @@ -328,14 +334,20 @@
    1.17                          }
    1.18                          break;
    1.19                      case ABS_X:
    1.20 -                        if (item->is_touchscreen) /* FIXME: temp hack */
    1.21 -                            break;
    1.22 -                        SDL_SendMouseMotion(mouse->focus, mouse->mouseID, SDL_FALSE, events[i].value, mouse->y);
    1.23 +                        if (item->is_touchscreen) {
    1.24 +                            if (item->touchscreen_data->max_slots != 1)
    1.25 +                                break;
    1.26 +                            item->touchscreen_data->slots[0].x = events[i].value;
    1.27 +                        } else
    1.28 +                            SDL_SendMouseMotion(mouse->focus, mouse->mouseID, SDL_FALSE, events[i].value, mouse->y);
    1.29                          break;
    1.30                      case ABS_Y:
    1.31 -                        if (item->is_touchscreen) /* FIXME: temp hack */
    1.32 -                            break;
    1.33 -                        SDL_SendMouseMotion(mouse->focus, mouse->mouseID, SDL_FALSE, mouse->x, events[i].value);
    1.34 +                        if (item->is_touchscreen) {
    1.35 +                            if (item->touchscreen_data->max_slots != 1)
    1.36 +                                break;
    1.37 +                            item->touchscreen_data->slots[0].y = events[i].value;
    1.38 +                        } else
    1.39 +                            SDL_SendMouseMotion(mouse->focus, mouse->mouseID, SDL_FALSE, mouse->x, events[i].value);
    1.40                          break;
    1.41                      default:
    1.42                          break;
    1.43 @@ -444,6 +456,7 @@
    1.44  SDL_EVDEV_init_touchscreen(SDL_evdevlist_item* item)
    1.45  {
    1.46      int ret, i;
    1.47 +    unsigned long xreq, yreq;
    1.48      char name[64];
    1.49      struct input_absinfo abs_info;
    1.50  
    1.51 @@ -466,7 +479,24 @@
    1.52          return SDL_OutOfMemory();
    1.53      }
    1.54  
    1.55 -    ret = ioctl(item->fd, EVIOCGABS(ABS_MT_POSITION_X), &abs_info);
    1.56 +    ret = ioctl(item->fd, EVIOCGABS(ABS_MT_SLOT), &abs_info);
    1.57 +    if (ret < 0) {
    1.58 +        SDL_free(item->touchscreen_data->name);
    1.59 +        SDL_free(item->touchscreen_data);
    1.60 +        return SDL_SetError("Failed to get evdev touchscreen limits");
    1.61 +    }
    1.62 +
    1.63 +    if (abs_info.maximum == 0) {
    1.64 +        item->touchscreen_data->max_slots = 1;
    1.65 +        xreq = EVIOCGABS(ABS_X);
    1.66 +        yreq = EVIOCGABS(ABS_Y);
    1.67 +    } else {
    1.68 +        item->touchscreen_data->max_slots = abs_info.maximum + 1;
    1.69 +        xreq = EVIOCGABS(ABS_MT_POSITION_X);
    1.70 +        yreq = EVIOCGABS(ABS_MT_POSITION_Y);
    1.71 +    }
    1.72 +
    1.73 +    ret = ioctl(item->fd, xreq, &abs_info);
    1.74      if (ret < 0) {
    1.75          SDL_free(item->touchscreen_data->name);
    1.76          SDL_free(item->touchscreen_data);
    1.77 @@ -476,7 +506,7 @@
    1.78      item->touchscreen_data->max_x = abs_info.maximum;
    1.79      item->touchscreen_data->range_x = abs_info.maximum - abs_info.minimum;
    1.80  
    1.81 -    ret = ioctl(item->fd, EVIOCGABS(ABS_MT_POSITION_Y), &abs_info);
    1.82 +    ret = ioctl(item->fd, yreq, &abs_info);
    1.83      if (ret < 0) {
    1.84          SDL_free(item->touchscreen_data->name);
    1.85          SDL_free(item->touchscreen_data);
    1.86 @@ -496,14 +526,6 @@
    1.87      item->touchscreen_data->max_pressure = abs_info.maximum;
    1.88      item->touchscreen_data->range_pressure = abs_info.maximum - abs_info.minimum;
    1.89  
    1.90 -    ret = ioctl(item->fd, EVIOCGABS(ABS_MT_SLOT), &abs_info);
    1.91 -    if (ret < 0) {
    1.92 -        SDL_free(item->touchscreen_data->name);
    1.93 -        SDL_free(item->touchscreen_data);
    1.94 -        return SDL_SetError("Failed to get evdev touchscreen limits");
    1.95 -    }
    1.96 -    item->touchscreen_data->max_slots = abs_info.maximum + 1;
    1.97 -
    1.98      item->touchscreen_data->slots = SDL_calloc(
    1.99          item->touchscreen_data->max_slots,
   1.100          sizeof(*item->touchscreen_data->slots));