wry icon indicating copy to clipboard operation
wry copied to clipboard

Add way to prevent GTK gestures from being intercepted by webkit

Open Jethril opened this issue 3 years ago • 0 comments

Is your feature request related to a problem? Please describe. While using Tauri on touchscreens, I realized that I am allowed to open a context-menu by long-pressing the app. I'm also allowed to zoom using a pinch-to-zoom gesture with three fingers, and with four fingers. Those events are directly handled by webkit.

I have no solution to properly restrict this behavior. This may also be a WebkitGtk feature request.

Describe the solution you'd like Wry should add a way to prevent those events from being intercepted and handled by webkit.

Describe alternatives you've considered As a workaround, I wrote the following Tauri plugin (which, I suppose, could be ported to Wry):

pub struct WindowCustomizerPlugin;

impl Default for WindowCustomizerPlugin {
    fn default() -> Self {
        Self
    }
}

impl<R: Runtime> Plugin<R> for WindowCustomizerPlugin {
    fn name(&self) -> &'static str {
        "Does not matter here"
    }

    fn created(&mut self, window: Window<R>) {
        let gtk_window = window.gtk_window().expect("GTK window should be accessible");

        // Retrieve the web view.
        let web_view = gtk_window
            .children()
            .into_iter()
            .next()
            .expect("GTK window should have a child")
            .downcast::<gtk::Box>()
            .expect("GTK window child should be a box")
            .children()
            .into_iter()
            .filter_map(|w| w.downcast::<WebView>().ok())
            .next()
            .expect("box should have a webview child");

        // This piece of code is responsible for preventing the context-menu (right-click menu) from being shown.
        web_view.connect_context_menu(|_, _, _, _| true);

        // Open the dev tools in debug builds, since the above instruction blocks it.
        #[cfg(debug_assertions)]
        if let Some(inspector) = web_view.inspector() {
            use webkit2gtk::traits::WebInspectorExt;

            inspector.show();
        }

        unsafe {
            // Disable the gesture zoom by removing its handlers.
            // If we "free" the data like the other handlers below, a segmentation fault is triggered when some
            // events are prevented from JavaScript.
            // See https://github.com/WebKit/WebKit/blob/c4c7b01e26d3142b0e0d456381c6d313399c3269/Source/WebKit/UIProcess/API/gtk/WebKitWebViewBase.cpp#L3017.
            if let Some(data) = web_view.data::<GestureZoom>("wk-view-zoom-gesture") {
                // This is a private API, but glib does not provide any way to query signal handlers that I didn't create.
                gobject_ffi::g_signal_handlers_destroy(data.as_ptr().cast());
            }

            // Disable some gestures by freeing their controllers.
            // This won't work with GTK 4, we would use the controller API for this.
            web_view.set_data("wk-view-long-press-gesture", ());
            web_view.set_data("wk-view-swipe-gesture", ());
        }
    }
}

Side note: the context menu could be disabled with the context-menu signal, but this alone would prevent JavaScript from receiving touch events properly.

Would you assign yourself to implement this feature?

  • [ ] Yes
  • [x] No (I don't know how to implement this with your practices, I never worked on Wry)

Jethril avatar Apr 07 '22 07:04 Jethril