Skip to content

Conversation

@moggiesir
Copy link
Contributor

@moggiesir moggiesir commented Jan 15, 2023

dbc31d0

Fix async scroll event propagation for GTK4
https://bugs.webkit.org/show_bug.cgi?id=243924
https://bugs.webkit.org/show_bug.cgi?id=245616

Reviewed by Michael Catanzaro.

Since GTK offers no way to asynchronously decide on whether an event should be
propagated or stopped and webkit doesn't want to block the UiProcess on event
handing in the WebProcess, webkit2gtk needs to use a bit of a hacky workaround.
This involves returning GDK_EVENT_STOP to the original event handling, sending
the event to the WebProcess for handling, which then asynchronously determines
whether the event was handled. If not, the webkit scroll handler is informed
that the "next" scroll event should be propagated instead of handled+stopped,
then re-emits the event for handling by GTK's run loop.

This works fine in GTK3 because there's an API to immediately run the event
loop for a given event (ensuring that the next event that the handler sees is
the intended one). For GTK4, the API for re-inserting an event appends the event
to the end of the event queue (despite what the documentation says), meaning the
next event the handler sees may not be the intended event - thus the wrong event
gets propagated and the just re-added event gets sent to the WebProcess again.

This coupled with the fact that GDK4 will synthesize scroll-start/scroll-end
events in some cases to ensure scroll events allows have the scroll-start,
scroll, scroll-end sequence can easily cause loops since it's not just 1 event
that needs to be propagated, it's up to 3.

To work better with the APIs that exist for GTK4, it seems like the best option
is to track the set of events that are "pending propagation" instead of relying
on the tight interlock of just ignoring the "next" event. The key handling
potentially also needs to be addressed similarly. Unfortunately, even tracking
the set of events to ignore is challenging because GTK4 can compress/coalesce
scroll events, meaning there will inevitably be some cases where we won't
propagate events that otherwise maybe should have been propagated (and
"unhandled" scroll events may cause some faster/slower than expected scrolling
when they get compressed into an not-yet-handled events).

Canonical link: https://commits.webkit.org/259530@main

35c4094

Misc iOS, tvOS & watchOS macOS Linux Windows
✅ 🧪 style ✅ 🛠 ios ✅ 🛠 mac ✅ 🛠 wpe ✅ 🛠 🧪 win
✅ 🛠 ios-sim ✅ 🛠 mac-AS-debug ✅ 🛠 gtk 🛠 wincairo
✅ 🧪 webkitperl ✅ 🧪 ios-wk2 ✅ 🧪 api-mac ✅ 🧪 gtk-wk2
✅ 🧪 api-ios ✅ 🧪 mac-wk1 ✅ 🧪 api-gtk
✅ 🛠 🧪 jsc ✅ 🛠 tv ✅ 🧪 mac-wk2 ✅ 🛠 jsc-armv7
✅ 🛠 🧪 jsc-arm64 ✅ 🛠 tv-sim 🧪 mac-AS-debug-wk2 ✅ 🧪 jsc-armv7-tests
✅ 🛠 watch ✅ 🧪 mac-wk2-stress ✅ 🛠 jsc-mips
✅ 🛠 🧪 merge ✅ 🛠 watch-sim ✅ 🧪 jsc-mips-tests

@moggiesir moggiesir requested a review from a team as a code owner January 15, 2023 01:35
@webkit-early-warning-system
Copy link
Collaborator

webkit-early-warning-system commented Jan 15, 2023

Copy link
Contributor

@mcatanzaro mcatanzaro left a comment

Choose a reason for hiding this comment

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

Thanks for this significant pull request. I've not quite wrapped my head around the event handling code, so we'll want to wait for Carlos Garcia to take a look at this. But I do have some preliminary comments.

@moggiesir moggiesir force-pushed the eng/GTK4-Infinite-loop-when-using-the-mouse-wheel branch from d247dfa to b827d61 Compare January 18, 2023 04:58
@moggiesir moggiesir force-pushed the eng/GTK4-Infinite-loop-when-using-the-mouse-wheel branch from b827d61 to 924f20f Compare January 18, 2023 05:09
@webkit-early-warning-system
Copy link
Collaborator

webkit-early-warning-system commented Jan 18, 2023

@carlosgcampos
Copy link
Contributor

Thanks for this significant pull request. I've not quite wrapped my head around the event handling code, so we'll want to wait for Carlos Garcia to take a look at this. But I do have some preliminary comments.

I don't have much time this week to look at this one. @Exalm could you review it, please?

@moggiesir moggiesir force-pushed the eng/GTK4-Infinite-loop-when-using-the-mouse-wheel branch from 924f20f to 15e3f79 Compare January 19, 2023 04:11
@moggiesir moggiesir force-pushed the eng/GTK4-Infinite-loop-when-using-the-mouse-wheel branch from 15e3f79 to cf40646 Compare January 19, 2023 04:19
@webkit-early-warning-system
Copy link
Collaborator

webkit-early-warning-system commented Jan 19, 2023

@moggiesir moggiesir force-pushed the eng/GTK4-Infinite-loop-when-using-the-mouse-wheel branch from cf40646 to 519d520 Compare January 19, 2023 07:41
@webkit-early-warning-system
Copy link
Collaborator

webkit-early-warning-system commented Jan 19, 2023

@moggiesir moggiesir force-pushed the eng/GTK4-Infinite-loop-when-using-the-mouse-wheel branch 2 times, most recently from d2119c0 to 3725068 Compare January 21, 2023 07:40
@webkit-early-warning-system
Copy link
Collaborator

webkit-early-warning-system commented Jan 21, 2023

@moggiesir moggiesir force-pushed the eng/GTK4-Infinite-loop-when-using-the-mouse-wheel branch from 3725068 to 1f239b9 Compare January 21, 2023 10:18
@webkit-early-warning-system
Copy link
Collaborator

webkit-early-warning-system commented Jan 21, 2023

@moggiesir
Copy link
Contributor Author

Any further comments?

Copy link
Contributor

@mcatanzaro mcatanzaro left a comment

Choose a reason for hiding this comment

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

Dunno how correct this it, but it looks plausible and seems better than what we have now, so I'm inclined to approve it, especially now that Exalm has reviewed it.

But I also have some more thoughts.

@moggiesir moggiesir force-pushed the eng/GTK4-Infinite-loop-when-using-the-mouse-wheel branch from 1f239b9 to 362e4b8 Compare January 28, 2023 04:38
@alice-mkh
Copy link
Contributor

I think it looks good, as in I don't see obvious regressions as before, but I haven't tried running it - I don't have an up to date webkit checkout atm and not going to pull/build it on a weekend.

@moggiesir moggiesir force-pushed the eng/GTK4-Infinite-loop-when-using-the-mouse-wheel branch from 362e4b8 to 35c4094 Compare January 28, 2023 19:40
@mcatanzaro mcatanzaro added the merge-queue Applied to send a pull request to merge-queue label Jan 28, 2023
https://bugs.webkit.org/show_bug.cgi?id=243924
https://bugs.webkit.org/show_bug.cgi?id=245616

Reviewed by Michael Catanzaro.

Since GTK offers no way to asynchronously decide on whether an event should be
propagated or stopped and webkit doesn't want to block the UiProcess on event
handing in the WebProcess, webkit2gtk needs to use a bit of a hacky workaround.
This involves returning GDK_EVENT_STOP to the original event handling, sending
the event to the WebProcess for handling, which then asynchronously determines
whether the event was handled. If not, the webkit scroll handler is informed
that the "next" scroll event should be propagated instead of handled+stopped,
then re-emits the event for handling by GTK's run loop.

This works fine in GTK3 because there's an API to immediately run the event
loop for a given event (ensuring that the next event that the handler sees is
the intended one). For GTK4, the API for re-inserting an event appends the event
to the end of the event queue (despite what the documentation says), meaning the
next event the handler sees may not be the intended event - thus the wrong event
gets propagated and the just re-added event gets sent to the WebProcess again.

This coupled with the fact that GDK4 will synthesize scroll-start/scroll-end
events in some cases to ensure scroll events allows have the scroll-start,
scroll, scroll-end sequence can easily cause loops since it's not just 1 event
that needs to be propagated, it's up to 3.

To work better with the APIs that exist for GTK4, it seems like the best option
is to track the set of events that are "pending propagation" instead of relying
on the tight interlock of just ignoring the "next" event. The key handling
potentially also needs to be addressed similarly. Unfortunately, even tracking
the set of events to ignore is challenging because GTK4 can compress/coalesce
scroll events, meaning there will inevitably be some cases where we won't
propagate events that otherwise maybe should have been propagated (and
"unhandled" scroll events may cause some faster/slower than expected scrolling
when they get compressed into an not-yet-handled events).

Canonical link: https://commits.webkit.org/259530@main
@webkit-early-warning-system webkit-early-warning-system force-pushed the eng/GTK4-Infinite-loop-when-using-the-mouse-wheel branch from 35c4094 to dbc31d0 Compare January 29, 2023 00:30
@webkit-commit-queue
Copy link
Collaborator

Committed 259530@main (dbc31d0): https://commits.webkit.org/259530@main

Reviewed commits have been landed. Closing PR #8663 and removing active labels.

@webkit-early-warning-system webkit-early-warning-system merged commit dbc31d0 into WebKit:main Jan 29, 2023
@webkit-commit-queue webkit-commit-queue removed the merge-queue Applied to send a pull request to merge-queue label Jan 29, 2023
@mcatanzaro
Copy link
Contributor

Planning to remove all of this code in https://bugs.webkit.org/show_bug.cgi?id=261348 and just never propagate the events...

@mcatanzaro
Copy link
Contributor

gnomesysadmins pushed a commit to GNOME/gtk that referenced this pull request Sep 8, 2023
This function is deprecated, but we should still document it properly.
It appends, not prepends. This is clear enough from its implementation,
but also we have practical experience with WebKit in:

WebKit/WebKit#8663
@moggiesir
Copy link
Contributor Author

If event re-injection is removed, won’t scroll propagation break? I.e if a scrollable webview is in a scrollable gtk panel, without further work in WebKit, it seems like you wouldn’t be able to scroll the gtk panel if your cursor is over the webview?

@mcatanzaro
Copy link
Contributor

Hm, good question. it depends: if the GTK panel handles the event in the capture phase, then it would not be possible to scroll the web view. If the panel handles the event in the bubble phase, then it would not be possible to scroll the panel.

But I assume the status quo is: not possible to scroll the panel unless the web view does not handle the scroll event (right?). That doesn't seem useful either?

If we need to, then we could emit a signal to indicate that the scroll event was unhandled, although without gdk_display_put_event() I'm not sure what applications could actually do with it.

@mcatanzaro
Copy link
Contributor

But I assume the status quo is: not possible to scroll the panel unless the web view does not handle the scroll event (right?). That doesn't seem useful either?

Actually I think this is exactly what email clients like Geary expect. You're probably right; removing this might be a problem.

@mcatanzaro
Copy link
Contributor

Left a comment here. I'm still tempted to remove the wheel event reinjection now to avoid applications beginning to depend on it when porting to GTK 4, but I fear this might prevent a few applications from porting.

gnomesysadmins pushed a commit to GNOME/gtk that referenced this pull request Sep 13, 2023
This function is deprecated, but we should still document it properly.
It appends, not prepends. This is clear enough from its implementation,
but also we have practical experience with WebKit in:

WebKit/WebKit#8663

Matthias prefers to avoid the prepend, append, start, and end
terminology altogether.
gnomesysadmins pushed a commit to GNOME/gtk that referenced this pull request Sep 13, 2023
This function is deprecated, but we should still document it properly.
It appends, not prepends. This is clear enough from its implementation,
but also we have practical experience with WebKit in:

WebKit/WebKit#8663

Matthias prefers to avoid the prepend, append, start, and end
terminology altogether.
gnomesysadmins pushed a commit to GNOME/gtk that referenced this pull request Sep 20, 2023
This function is deprecated, but we should still document it properly.
It appends, not prepends. This is clear enough from its implementation,
but also we have practical experience with WebKit in:

WebKit/WebKit#8663

Matthias prefers to avoid the prepend, append, start, and end
terminology altogether.
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.

6 participants