I really like the new Raspberry pi display.
One of the things I was really looking forward to was using it with OpenFL.
But out of the box SDL2 wasn’t supporting the display in the mode I am running OpenFL namely without x11.
So I decided to do a little digging.
I found that mouse and keyboard devices are being handled in sdl_udev and sdl_evdev.
Basically udev was looking for and identifying input devices and evdev was handling incoming events from identified devices.
I could see that udev was finding an ID_INPUT_TOUCHSCREEN device, but there was nothing more than a comment after that.
So I decided to try and trick udev by identifying the touchscreen as a combined mouse and keyboard device.
1 2 3 4 5 6 7 8 9 10 |
val = _this->udev_device_get_property_value(dev, "ID_INPUT_TOUCHSCREEN"); if (val != NULL && SDL_strcmp(val, "1") == 0 ) { devclass |= SDL_UDEV_DEVICE_TOUCHSCREEN; } // I defined SDL_UDEV_DEVICE_TOUCHSCREEN = 0x0003 in SDL_udev.h // combining the bitmasks for // SDL_UDEV_DEVICE_MOUSE = 0x0001, // and // SDL_UDEV_DEVICE_KEYBOARD = 0x0002, |
Immediately I could move the mouse pointer but a touch triggered a key-event with an unhandled value of 330.
( later I found that this key is defined in linux/input.h as BTN_TOUCH )
So I added the button to the if statement that was catching the mousebutton values in SDL_evdev.c
and cheated a bit by changing it to mouse-button 0
1 2 3 4 5 6 7 8 9 10 11 |
case EV_KEY: if (events[i].code >= BTN_MOUSE && events[i].code < BTN_MOUSE + SDL_arraysize(EVDEV_MouseButtons) || events[i].code==BTN_TOUCH ) { mouse_button = events[i].code - BTN_MOUSE; if(events[i].code == BTN_TOUCH ) mouse_button = 0; // map BTN_TOUCH to mousebutton 0; if (events[i].value == 0) { SDL_SendMouseButton(mouse->focus, mouse->mouseID, SDL_RELEASED, EVDEV_MouseButtons[mouse_button]); } else if (events[i].value == 1) { SDL_SendMouseButton(mouse->focus, mouse->mouseID, SDL_PRESSED, EVDEV_MouseButtons[mouse_button]); } break; } |
I thought that it was working until I noticed something strange. It felt like the mousedown event was out of sync.
So I opened the utility evtest on an ssh session to see what was going on.
If found that the touchscreen was firing 2 unhandled events before the BTN_TOUCH event:
1 2 3 4 5 6 |
Event: time 1444328996.055029, type 3 (EV_ABS), code 57 (ABS_MT_TRACKING_ID), value 109 Event: time 1444328996.055029, type 3 (EV_ABS), code 53 (ABS_MT_POSITION_X), value 719 Event: time 1444328996.055029, type 3 (EV_ABS), code 54 (ABS_MT_POSITION_Y), value 138 Event: time 1444328996.055029, type 1 (EV_KEY), code 330 (BTN_TOUCH), value 1 Event: time 1444328996.055029, type 3 (EV_ABS), code 0 (ABS_X), value 719 Event: time 1444328996.055029, type 3 (EV_ABS), code 1 (ABS_Y), value 138 |
the code was only handling the ABS_X events so indeed the Touch event came before the x en y positions where handled.
So I added these 2 new events:
1 2 3 4 5 6 7 8 9 10 |
case EV_ABS: switch(events[i].code) { case ABS_X: case ABS_MT_POSITION_X: SDL_SendMouseMotion(mouse->focus, mouse->mouseID, SDL_FALSE, events[i].value, mouse->y); break; case ABS_Y: case ABS_MT_POSITION_Y: SDL_SendMouseMotion(mouse->focus, mouse->mouseID, SDL_FALSE, mouse->x, events[i].value); break; |
Et Voila!, the touch screen is working as a mouse.
For proper multitouch a different approach is needed.
But for testing this hack works quite well.