From 374449e40ac2d520a5ba146a1f472b5d845cad9e Mon Sep 17 00:00:00 2001 From: DrUlysses Date: Mon, 1 Jun 2026 14:08:19 +0200 Subject: [PATCH 1/2] Fix for #43 --- .../webview/wry/WryWebViewPanel.kt | 6 +- wrywebview/src/main/rust/lib.rs | 79 ++----------------- 2 files changed, 11 insertions(+), 74 deletions(-) diff --git a/wrywebview/src/main/kotlin/io/github/kdroidfilter/webview/wry/WryWebViewPanel.kt b/wrywebview/src/main/kotlin/io/github/kdroidfilter/webview/wry/WryWebViewPanel.kt index b4006d5..7097c77 100644 --- a/wrywebview/src/main/kotlin/io/github/kdroidfilter/webview/wry/WryWebViewPanel.kt +++ b/wrywebview/src/main/kotlin/io/github/kdroidfilter/webview/wry/WryWebViewPanel.kt @@ -60,6 +60,7 @@ class WryWebViewPanel( // Request focus when clicked to capture keyboard events host.addMouseListener(object : MouseAdapter() { override fun mousePressed(e: MouseEvent?) { + host.requestFocusInWindow() requestWebViewFocus() } }) @@ -342,7 +343,10 @@ class WryWebViewPanel( fun isReady(): Boolean = webviewId != null fun requestWebViewFocus() { - val action = { webviewId?.let { NativeBindings.focus(it) } } + val action = { + host.requestFocusInWindow() + webviewId?.let { NativeBindings.focus(it) } + } if (SwingUtilities.isEventDispatchThread()) { action() } else { diff --git a/wrywebview/src/main/rust/lib.rs b/wrywebview/src/main/rust/lib.rs index 62a74f5..6bc2f9f 100644 --- a/wrywebview/src/main/rust/lib.rs +++ b/wrywebview/src/main/rust/lib.rs @@ -355,51 +355,20 @@ fn create_webview_inner( // On Linux, set up focus handling for the GTK widget #[cfg(target_os = "linux")] { - use gdkx11::glib::translate::ToGlibPtr; - use gdkx11::glib::Cast; - use gdkx11::X11Display; use gtk::prelude::WidgetExt; let gtk_widget = webview.webview(); gtk_widget.set_can_focus(true); - // Connect to button-press-event to grab focus when clicked using X11 + // Connect to button-press-event to grab focus when clicked. + // Avoid forcing raw X11 focus here because the host hierarchy may be + // managed by AWT/Swing and direct XSetInputFocus can desynchronize focus. gtk_widget.connect_button_press_event(|widget, _event| { wry_log!("[wrywebview] button_press_event -> grab_focus"); - - // Use X11 focus directly for proper keyboard input - if let Some(gdk_window) = widget.window() { - if let Some(display) = gdk::Display::default() { - if let Ok(x11_display) = display.downcast::() { - unsafe { - let gdk_window_ptr: *mut gdk::ffi::GdkWindow = gdk_window.to_glib_none().0; - let xid = gdkx11::ffi::gdk_x11_window_get_xid( - gdk_window_ptr as *mut gdkx11::ffi::GdkX11Window, - ); - - if xid != 0 { - let x11_display_ptr: *mut gdkx11::ffi::GdkX11Display = x11_display.to_glib_none().0; - let x_display = gdkx11::ffi::gdk_x11_display_get_xdisplay(x11_display_ptr); - - if !x_display.is_null() { - x11::xlib::XSetInputFocus( - x_display as *mut x11::xlib::Display, - xid, - x11::xlib::RevertToParent, - x11::xlib::CurrentTime, - ); - wry_log!("[wrywebview] button_press XSetInputFocus xid=0x{:x}", xid); - } - } - } - } - } - } - widget.grab_focus(); gtk::glib::Propagation::Proceed }); - wry_log!("[wrywebview] gtk focus handling configured with X11 support"); + wry_log!("[wrywebview] gtk focus handling configured"); } let id = register(webview, state, web_context)?; @@ -723,13 +692,10 @@ pub fn reload(id: u64) -> Result<(), WebViewError> { fn focus_inner(id: u64) -> Result<(), WebViewError> { wry_log!("[wrywebview] focus id={}", id); with_webview(id, |webview| { - // On Linux, we need to use X11 focus directly since the GTK widget - // is embedded in a foreign (AWT/Swing) window hierarchy + // On Linux, keep focus changes within GTK/Wry to avoid desynchronizing + // focus with the host AWT/Swing hierarchy. #[cfg(target_os = "linux")] { - use gdkx11::glib::translate::ToGlibPtr; - use gdkx11::glib::Cast; - use gdkx11::X11Display; use gtk::prelude::WidgetExt; let gtk_widget = webview.webview(); @@ -740,39 +706,6 @@ fn focus_inner(id: u64) -> Result<(), WebViewError> { gtk_widget.realize(); } - // Get the GDK window and use X11 to set focus - if let Some(gdk_window) = gtk_widget.window() { - // Get the X11 display from GDK - if let Some(display) = gdk::Display::default() { - if let Ok(x11_display) = display.downcast::() { - unsafe { - // Get the X11 window ID (XID) from the GDK window - let gdk_window_ptr: *mut gdk::ffi::GdkWindow = gdk_window.to_glib_none().0; - let xid = gdkx11::ffi::gdk_x11_window_get_xid( - gdk_window_ptr as *mut gdkx11::ffi::GdkX11Window, - ); - - if xid != 0 { - // Get the raw X11 display pointer - let x11_display_ptr: *mut gdkx11::ffi::GdkX11Display = x11_display.to_glib_none().0; - let x_display = gdkx11::ffi::gdk_x11_display_get_xdisplay(x11_display_ptr); - - if !x_display.is_null() { - // XSetInputFocus: RevertToParent = 2, CurrentTime = 0 - x11::xlib::XSetInputFocus( - x_display as *mut x11::xlib::Display, - xid, - x11::xlib::RevertToParent, - x11::xlib::CurrentTime, - ); - wry_log!("[wrywebview] XSetInputFocus xid=0x{:x}", xid); - } - } - } - } - } - } - // Also call GTK grab_focus as a fallback gtk_widget.grab_focus(); wry_log!("[wrywebview] gtk grab_focus called"); From 06950ac6f3980eca6e509d4eedf41bc475f48af6 Mon Sep 17 00:00:00 2001 From: DrUlysses Date: Mon, 1 Jun 2026 14:16:35 +0200 Subject: [PATCH 2/2] Fix for #43 --- .../io/github/kdroidfilter/webview/wry/WryWebViewPanel.kt | 2 -- 1 file changed, 2 deletions(-) diff --git a/wrywebview/src/main/kotlin/io/github/kdroidfilter/webview/wry/WryWebViewPanel.kt b/wrywebview/src/main/kotlin/io/github/kdroidfilter/webview/wry/WryWebViewPanel.kt index 7097c77..2a1100b 100644 --- a/wrywebview/src/main/kotlin/io/github/kdroidfilter/webview/wry/WryWebViewPanel.kt +++ b/wrywebview/src/main/kotlin/io/github/kdroidfilter/webview/wry/WryWebViewPanel.kt @@ -60,7 +60,6 @@ class WryWebViewPanel( // Request focus when clicked to capture keyboard events host.addMouseListener(object : MouseAdapter() { override fun mousePressed(e: MouseEvent?) { - host.requestFocusInWindow() requestWebViewFocus() } }) @@ -344,7 +343,6 @@ class WryWebViewPanel( fun requestWebViewFocus() { val action = { - host.requestFocusInWindow() webviewId?.let { NativeBindings.focus(it) } } if (SwingUtilities.isEventDispatchThread()) {