swaywm / sway

i3-compatible Wayland compositor
https://swaywm.org
MIT License
14.7k stars 1.11k forks source link

xwayland popups not working in native wayland applications with elogind 246.9 #5971

Open Dudemanguy opened 3 years ago

Dudemanguy commented 3 years ago

Description: This is a really weird, specific issue, so I'll give the rundown. I run ibus + mozc to type in Japanese (I have a keybind setup that executes a script to toggle ibus engines). When typing the characters, a small popup window is displayed that lets you choose the kanji/whatever you want to select. When doing this in a native wayland application, the popup just shows up in the top left since whatever is drawing it (mozc I guess; dunno) is an xorg application. No big deal, it works fine.

However, with the release of elogind 246.9, this actually broke. I actually bisected the exact elogind commit that messes up this behavior. If you revert that commit + fix some minor merge conflicts, it works normally again. What does elogind have to do with xwayland popups? No idea. I do not know if this also happens with systemd or if it is specific to elogind.

The actual bug is just that the selection popup flashes for a second and appears to crash/disappear. This makes it impossible to type Japanese (or any other language that depends on an IME in this way). It's also worth noting that this only happens in wayland applications. If you are inputting into an xwayland application and change the ibus engine, it works just fine. Also, this only happens in sway. I tested GNOME and it was able to use ibus normally.

So I guess to sum it up, somehow adding the SetType method to elogind messes up xwayland popups being generated in native wayland applications in Sway. The ibus example is the only thing I'm personally aware that suffers from this but maybe there's something else.

emersion commented 3 years ago

ibus is probably reading the XDG_SESSION_TYPE env var. It really shouldn't do this.

joanbm commented 2 years ago

I'm experiencing a similar issue on Arch Linux with Systemd 250.3, wlroot 0.15.1 and Sway 1.7 and ibus 1.5.25 with the input-method-v2 PR. In my case it's with Uniemoji input method.

The symptoms are the same, on XWayland (or just plain X11) the popup showing the list of emojis works fine, but on pure Wayland, the popup shows for a split second on the top left then hides.

I can see that here update_lookup_table is called in ibus-ui-gtk3 with the correct list to show, but after this I immediately get a call with visible=false that hides the window. Trying to trace it, I see that when the popup opens a lot of focus in/out events are generated which ultimately end up hiding the window, but so far I've been unable to find the origin or some way to ignore them without breaking everything.

It'd be interesting to see if someone is actually able to get the popup/lookup table to show up on Sway at all or it's broken for everybody.

Dudemanguy commented 2 years ago

For the record, I ended up switching to fcitx which works okay (I assume it uses native wayland), but yeah as far as I know this issue still exists.

joanbm commented 2 years ago

I think I may have it mostly figured out. When the candidates window pops up, this function is called and whether to give it focus is decided here: https://github.com/swaywm/sway/blob/69b430201cb19c666f102586b18f1dfbda7c44a3/sway/desktop/xwayland.c#L87

This condition passes and Sway gives focus to the new window, this makes IBus think that the edit event is over and closes the candidates window.

I am pretty sure that the candidates window is not supposed to receive focus since it's created as GTK_WINDOW_POPUP and I don't seem to receive any focus change events on X11. I'm not 100% sure which X11 attribute determines it shouldn't get focus on mapping, but it's probably override_redirect? I tried the following patch to wlroots, and now the candidates windows works fine, minus it being located (0, 0):

diff --git a/xwayland/xwm.c b/xwayland/xwm.c
index 0c199269..2e82d55a 100644
--- a/xwayland/xwm.c
+++ b/xwayland/xwm.c
@@ -2211,7 +2211,7 @@ bool wlr_xwayland_or_surface_wants_focus(
        }
    }

-   return true;
+   return !xsurface->override_redirect;
 }

 enum wlr_xwayland_icccm_input_model wlr_xwayland_icccm_input_model(

(Though, I have no idea why in OPs case it depended on an elogind commit)

emersion commented 2 years ago

wlr_xwayland_or_surface_wants_focus is only called when the surface is O-R. So your change is essentially making wlr_xwayland_or_surface_wants_focus always return false.

joanbm commented 2 years ago

Doh, makes sense... Though as far as I can see override_redirect windows shouldn't actually ever be given focus, it's just in wlroots as a kind of heuristic to deal with X/Wayland mismatches: https://gitlab.freedesktop.org/wlroots/wlroots/-/commit/81cc842f8f27461742710b4195443da64c7bfeef

I'll try to understand the situation better to see if I can come up with something to unbreak IBus while not breaking anything else.

emersion commented 2 years ago

Yeah, this heuristic is a hack and the proper logic to use to decide to give focus is wlr_xwayland_icccm_input_model.

Though as far as I can see override_redirect windows shouldn't actually ever be given focus

Some O-R should be given focus depending on the ICCCM input model.

joanbm commented 2 years ago

In this case the IBus window has both the WM_TAKE_FOCUS protocol and a focus hint.

Perhaps the best long-term solution would be to improve ibus-ui-gtk3 to work on Wayland (it mostly does, but by default it forces X11 since some of the features only work there) then create the window with gtk-layer-shell.

joanbm commented 2 years ago

A better workaround is to play along the wlroots heuristic and set up a type hint on the ibus-ui-gtk3 helper windows (on ibus), to avoids breaking the focus logic for rofi/etc. on wlroots:

From 39e1ba9c7b15c6bfb1b3a8bf34ced8f0ad7a6e51 Mon Sep 17 00:00:00 2001
From: Joan Bruguera <joanbrugueram@gmail.com>
Date: Fri, 11 Feb 2022 21:39:36 +0100
Subject: [PATCH] ui/gtk3: POPUP_MENU hint on candidate & property panels

In practical terms, this makes this panels work properly on Sway, and possibly
other compositors based on wlroots, when ibus-ui-gtk is running on XWayland.

See: https://github.com/swaywm/sway/issues/5971
---
 ui/gtk3/candidatepanel.vala | 1 +
 ui/gtk3/propertypanel.vala  | 1 +
 2 files changed, 2 insertions(+)

diff --git a/ui/gtk3/candidatepanel.vala b/ui/gtk3/candidatepanel.vala
index 57544df..db39ebc 100644
--- a/ui/gtk3/candidatepanel.vala
+++ b/ui/gtk3/candidatepanel.vala
@@ -53,6 +53,7 @@ public class CandidatePanel : Gtk.Box{
         );

         m_toplevel = new Gtk.Window(Gtk.WindowType.POPUP);
+        m_toplevel.set_type_hint(Gdk.WindowTypeHint.POPUP_MENU);
         m_toplevel.add_events(Gdk.EventMask.BUTTON_PRESS_MASK);
         m_toplevel.button_press_event.connect((w, e) => {
             if (e.button != 1 || (e.state & Gdk.ModifierType.CONTROL_MASK) == 0)
diff --git a/ui/gtk3/propertypanel.vala b/ui/gtk3/propertypanel.vala
index b94b2b7..b0180fe 100644
--- a/ui/gtk3/propertypanel.vala
+++ b/ui/gtk3/propertypanel.vala
@@ -60,6 +60,7 @@ public class PropertyPanel : Gtk.Box {
 #endif

         m_toplevel = new Gtk.Window(Gtk.WindowType.POPUP);
+        m_toplevel.set_type_hint(Gdk.WindowTypeHint.POPUP_MENU);
         m_toplevel.add_events(Gdk.EventMask.BUTTON_PRESS_MASK);

         Handle handle = new Handle();
-- 
2.35.1

Though I think the proper solution is to make ui-ibus-gtk3 work on pure Wayland and get everything working there properly.

PS (2023-12-31): Since IBus 1.5.29, ibus-ui-gtk3 has some Wayland support but it doesn't work with Sway due to it lacking input-method v2 support. To keep it mostly working (IBus ≤1.5.29 behaviour) you will need to start it in X11 mode like this: ibus-daemon -drx --panel "/usr/bin/env GDK_BACKEND=x11 /usr/lib/ibus/ibus-ui-gtk3"

Moelf commented 10 months ago

you will need to start it in X11 mode like this: ibus-daemon -drx --panel "/usr/bin/env GDK_BACKEND=x11 /usr/lib/ibus/ibus-ui-gtk3"

this indeed works in a pretty janky way, for some applications, the popup candidate panel jitters/flashes at one corner of the screen and seems to lose focus/re-focus very frequently...

is the anticipated fix for Sway-ecosystem to support input-method v2? (#7226)

joanbm commented 10 months ago

the popup candidate panel jitters/flashes at one corner of the screen and seems to lose focus/re-focus very frequently...

The "at one corner of the screen" part happens when the candidate panel is invoked from a native Wayland app, and as far as I know is unfixable since I don't think an application running under Xwayland can tell where to put the candidate window in that case. I think the only real way ahead is to fix ibus-ui-gtk3 so it can run under Wayland mode in Sway.

The "jitters/flashes [...] and seems to lose focus/re-focus very frequently" is fixed for me when applying the patch above (setting m_toplevel.set_type_hint(Gdk.WindowTypeHint.POPUP_MENU); on the candiate panel window). But the long-term solution should also be to get ibus-ui-gtk3 to run under Wayland mode in Sway.

is the anticipated fix for Sway-ecosystem to support input-method v2? (#7226)

I'm unsure about the minimal list needed to get it onto a usable state, but currently IBus only supports input-method-v1 and wlroots/Sway only supports input-method-v2 so I believe https://github.com/ibus/ibus/pull/2256 is needed? And probably the PR you linked is also needed as well.