Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Libinput and fbdev improvements for unl0kr #280

Open
wants to merge 14 commits into
base: master
Choose a base branch
from

Conversation

calebccff
Copy link

Add a framebuffer quirk to force the display to refresh after every draw, this is needed for some quirky panels and DRM/fbdev emulation setups. It requires that the display buffer is set to the same size as the whole framebuffer so that the entire display can be flushed at once if needed, otherwise there is tearing.

Also use pthreads and a small circular queue to stop the libinput driver from dropping inputs. The LVGL tickrate can't always keep up and this ensures that inputs aren't dropped.

The keypad support needs to be tested.

Cc: @Johennes

Copy link
Contributor

@Johennes Johennes left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pretty amazing stuff! Thanks @calebccff!

I've only given it a quick look this morning. Will try to do some testing against https://gitlab.com/cherrypicker/unl0kr/-/merge_requests/21 this week.

@kisvegabor, I know, lv_drivers is supposed to be deprecated in future. It'll be very helpful to have these changes merged though because https://gitlab.com/cherrypicker/unl0kr still depends on it.

We already started migrating to lvgl master in https://gitlab.com/cherrypicker/unl0kr/-/merge_requests/20 and we'll port the changes to the fbdev driver and the libinput driver, too, as part of this.

@calebccff calebccff force-pushed the caleb/unl0kr-disp-input-fixes branch from 131c16c to 0cfcdbb Compare June 5, 2023 13:32
Copy link
Member

@kisvegabor kisvegabor left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Really nice, thank you!

We can merge it here, but yeah... it'd be great to add these updates to master as well. 🙂

display/fbdev.h Outdated Show resolved Hide resolved
indev/libinput.c Show resolved Hide resolved
indev/libinput.c Show resolved Hide resolved
indev/libinput.c Outdated Show resolved Hide resolved
@calebccff calebccff force-pushed the caleb/unl0kr-disp-input-fixes branch from 0cfcdbb to f0f053a Compare June 24, 2023 22:10
@calebccff
Copy link
Author

Totally forgot to push 😅 sorry for the wait. The touch/pointer handling was actually pretty broken... Anyways, hopefully this is good to go now!

@Johennes
Copy link
Contributor

Thanks for updating the PR @calebccff and sorry for the delay. I will take a look at this and test it within unl0kr but I won't manage before next week, unfortunately.

Copy link
Contributor

@Johennes Johennes left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sorry again for the delay. I reviewed the code and tested it with https://gitlab.com/cherrypicker/unl0kr/-/merge_requests/21 in unl0kr.

Pointer devices don't currently work correctly because their delta motion logic needs special handling with the new event buffer.

There is possibly also a problem with the mutex. I didn't notice any issues related to that when testing but I think the mutex initialization is missing and might just work accidentally in unl0kr.

indev/libinput.c Outdated Show resolved Hide resolved
indev/libinput.c Outdated Show resolved Hide resolved
indev/libinput.c Outdated Show resolved Hide resolved
indev/libinput.c Outdated Show resolved Hide resolved
calebccff and others added 6 commits July 11, 2023 15:33
This is needed specifically for Qualcomm devices using DRM fbdev
emulation, it is probably useful for other platforms using fbdev
emulation.
Libinput doesn't buffer events, so hook up a dedicated thread per input
device and a small circular queue to buffer input events. This fixes the
dropped input issue so you can type much faster. If there are too many
events, the oldest events in the queue will be dropped.
When typing fast with thumbs, you might hit a key while your other thumb
is already pressing a key, however this confuses indev quite a lot.

For example, you'll press a key (say 'h') with your right thumb, then
before releasing your thumb you'll press the 'e' key with your left
thumb, and then finally release the 'h' key followed by the 'e' key.

This should result in "he" being typed, but usually results in an "e".
Indev assumes that a pointer release will always be for whatever the
last position was. This is reasonable for mice but not for multitouch
displays.

This workaround detects this scenario and inserts two dummy events,
first a "pressed" state with the coordinates of the first finger (the
'h' key), then a release event, triggering the keypress, then it sends
another pressed events with the position of the second finger (the 'e'
key) so that if the next event is that finger releasing, the position
will be correct.
@calebccff calebccff force-pushed the caleb/unl0kr-disp-input-fixes branch from 7a1f200 to 878388c Compare July 11, 2023 14:38
@calebccff
Copy link
Author

Rebased on master and picked up Johannes' fixes (Thanks a lot for that!). Should be good to go! Tested again with unl0kr.

I added a new commit to properly handle typing with two thumbs by injecting some fake events, with this you can type as fast as you want with your thumbs and not miss an input which is really nice for unl0kr. See the commit description for more details.

I get that this is a bit of a hack, I'm happy to drop it if it blocks the rest of the series.

indev/libinput.c Outdated Show resolved Hide resolved
indev/libinput.c Outdated Show resolved Hide resolved
@Johennes
Copy link
Contributor

Johennes commented Jul 14, 2023

Rebased on master and picked up Johannes' fixes (Thanks a lot for that!). Should be good to go! Tested again with unl0kr.

I added a new commit to properly handle typing with two thumbs by injecting some fake events, with this you can type as fast as you want with your thumbs and not miss an input which is really nice for unl0kr. See the commit description for more details.

I get that this is a bit of a hack, I'm happy to drop it if it blocks the rest of the series.

The slot stuff is clever!

One possible issue I'm seeing is that you're writing state->slots from both the polling thread and the LVGL input handler. The locking is avoiding concurrent writes. But depending on how fast events enter and leave the queue, I think it's possible for later multi-touch events to already have overridden the slots array filled by earlier ones before you could use it?

I guess generally it'd be nice if LVGL itself supported multi-touch but the event injection strikes me as an acceptable workaround until then (especially given that we already do some event rewriting with is_relative).

indev/libinput.c Outdated
evt->point.y += libinput_event_pointer_get_dy(pointer_event);
evt->point.x = LV_CLAMP(0, evt->point.x, drv->hor_res - 1);
evt->point.y = LV_CLAMP(0, evt->point.y, drv->ver_res - 1);
evt->is_relative = true;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

One more issue that I just found is that the code currently doesn't support dragging anymore. E.g. if you click and hold but even just slightly move the cursor, that triggers a release because we're not setting evt->pressed here.

Unfortunately, libinput_event_pointer_get_button_state(..) doesn't seem to work for motion events. So we cannot use it here.

We could maybe define two relativity flags, is_relative_position (which would mean add up x and y to the latest state) and is_relative_button (which would mean inherit the pressed value from the latest state). LIBINPUT_EVENT_POINTER_MOTION events would then require both is_relative_position and is_relative_button while LIBINPUT_EVENT_POINTER_BUTTON events would only require is_relative_position.

Does that make sense?

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I haven't tested it but I just added a pointer_button_down property to libinput_drv_state_t, had that attribute be updated on LIBINPUT_EVENT_POINTER_BUTTON and set evt->pressed based on that. I also made LIBINPUT_EVENT_POINTER_BUTTON fallthrough to LIBINPUT_EVENT_POINTER_MOTION so that evt->point is set.

I think that should work?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nice! Yes, that seems to work. This now actually makes me think we could do the same for the delta movements. Instead of doing the weird is_relative thing when consuming events, just store last position we've seen in state and add the delta from libinput to it.

Copy link
Contributor

@Johennes Johennes Jul 26, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Have made it so. This thread can be resolved now.

@Johennes
Copy link
Contributor

One possible issue I'm seeing is that you're writing state->slots from both the polling thread and the LVGL input handler. The locking is avoiding concurrent writes. But depending on how fast events enter and leave the queue, I think it's possible for later multi-touch events to already have overridden the slots array filled by earlier ones before you could use it?

Actually, I think you can work around that by doing the event injection when reading from libinput as opposed to when consuming the cached events. The slots array is guaranteed to only be filled by events preceding the current one at that point.

@Johennes
Copy link
Contributor

Actually, I think you can work around that by doing the event injection when reading from libinput as opposed to when consuming the cached events. The slots array is guaranteed to only be filled by events preceding the current one at that point.

This has been implemented, too, now.

@Johennes
Copy link
Contributor

Johennes commented Jul 27, 2023

@kisvegabor this is now done from our end and ready for your review. I've tested it in unl0kr with touch, pointer and keyboard devices. Once we make another unl0kr release, I'll start working on porting this into lvgl master.

Johennes and others added 3 commits September 30, 2023 20:28
This enables fast typing on hardware keyboards as keys are no longer forgotten.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants