hyprwm / Hyprland

Hyprland is an independent, highly customizable, dynamic tiling Wayland compositor that doesn't sacrifice on its looks.
https://hyprland.org
BSD 3-Clause "New" or "Revised" License
21.22k stars 895 forks source link

Xwayland doesn't unfocus when switching to wayland client #7698

Closed sungyoonc closed 1 month ago

sungyoonc commented 1 month ago

Regression?

Yes

System Info and Version

System/Version info ```sh Hyprland, built from branch main at commit 312411fc7073143a8bf1fc3ba23ef403b7d15eee (windows: support size with pseudo tiled). Date: Sun Sep 8 08:46:46 2024 Tag: v0.42.0-126-g312411fc, commits: 5195 flags: (if any) System Information: System name: Linux Node name: acacia Release: 6.10.8-arch1-1 Version: #1 SMP PREEMPT_DYNAMIC Wed, 04 Sep 2024 15:16:37 +0000 GPU information: 00:02.0 VGA compatible controller [0300]: Intel Corporation Raptor Lake-P [Iris Xe Graphics] [8086:a7a0] (rev 04) (prog-if 00 [VGA controller]) os-release: NAME="Arch Linux" PRETTY_NAME="Arch Linux" ID=arch BUILD_ID=rolling ANSI_COLOR="38;2;23;147;209" HOME_URL="https://archlinux.org/" DOCUMENTATION_URL="https://wiki.archlinux.org/" SUPPORT_URL="https://bbs.archlinux.org/" BUG_REPORT_URL="https://gitlab.archlinux.org/groups/archlinux/-/issues" PRIVACY_POLICY_URL="https://terms.archlinux.org/docs/privacy-policy/" LOGO=archlinux-logo plugins: ======Config-Start====== Config File: /home/fox/.config/hypr/hyprland.conf: Read Succeeded # See https://wiki.hyprland.org/Configuring/Keywords/ for more # See https://wiki.hyprland.org/Configuring/Monitors/ monitor = eDP-1,2880x1800@120,auto-left,1.8,vrr,1 monitor = DP-3,1920x1080@60,auto-right,auto monitor=,preferred,auto,auto # Idle configuration, only run when hypridle is not running exec-once = pidof hypridle || hypridle & source = ~/.config/hypr/config.d/env.conf source = ~/.config/hypr/config.d/ime.conf source = ~/.config/hypr/config.d/input.conf source = ~/.config/hypr/config.d/layout.conf source = ~/.config/hypr/config.d/visual.conf source = ~/.config/hypr/config.d/rules.conf source = ~/.config/hypr/config.d/keybinds.conf source = ~/.config/hypr/config.d/autostart.conf xwayland { force_zero_scaling = true } misc { # See https://wiki.hyprland.org/Configuring/Variables/#misc for more initial_workspace_tracking = 1 disable_splash_rendering = true disable_hyprland_logo = true # Lower sent frame when nothing is happening on screen vfr = true } debug { disable_logs = false } Config File: /home/fox/.config/hypr/config.d/env.conf: Read Succeeded # Some default env vars. env = XCURSOR_SIZE,24 env = QT_QPA_PLATFORM,wayland # Jetbrains Intellij jbr21 env = IDEA_JDK,/usr/lib/jvm/java-21-jetbrains/ Config File: /home/fox/.config/hypr/config.d/ime.conf: Read Succeeded # Autostart ime exec-once = fcitx5 & # Set env for ime env = QT_IM_MODULE,fcitx env = SDL_IM_MODULE,fcitx env = XMODIFIERS,@im=fcitx # Restart fcitx to fix alacritty not waking it up bindn = , escape, exec, /usr/bin/fcitx5-remote -s keyboard-us & Config File: /home/fox/.config/hypr/config.d/input.conf: Read Succeeded # For all categories, see https://wiki.hyprland.org/Configuring/Variables/ cursor { inactive_timeout = 5 enable_hyprcursor = true } input { kb_layout = us kb_variant = kb_model = # Use ralt and rctrl for korean input kb_options = korean:ralt_hangul,korean:rctrl_hanja kb_rules = follow_mouse = 1 touchpad { natural_scroll = true drag_lock = true } sensitivity = 0 # -1.0 - 1.0, 0 means no modification. } gestures { # See https://wiki.hyprland.org/Configuring/Variables/ for more workspace_swipe = false } # Example per-device config # See https://wiki.hyprland.org/Configuring/Keywords/#executing for more device { name = epic-mouse-v1 sensitivity = -0.5 } $DEVICE_TOUCHPAD_ENABLED = true device { name = znt0001:00-14e5:650e-touchpad enabled = $DEVICE_TOUCHPAD_ENABLED } Config File: /home/fox/.config/hypr/config.d/layout.conf: Read Succeeded dwindle { # See https://wiki.hyprland.org/Configuring/Dwindle-Layout/ for more pseudotile = yes # master switch for pseudotiling. Enabling is bound to mainMod + P in the keybinds section below preserve_split = yes # you probably want this } Config File: /home/fox/.config/hypr/config.d/visual.conf: Read Succeeded # Dark mode exec = gsettings set org.gnome.desktop.interface color-scheme "prefer-dark" # for GTK4 apps env = QT_QPA_PLATFORMTHEME,qt6ct # for Qt apps, `qt6ct` to configure # Import catppuccin colors source = ~/.config/hypr/themes/frappe.conf # Wallpaper exec-once = swaybg -i ~/.local/share/wallpapers/dark-cat-rosewater.png & # Hyprcursor env = HYPRCURSOR_THEME,Bibata-Modern-Ice env = HYPRCURSOR_SIZE,24 # XCursor env = XCURSOR_THEME,Bibata-Modern-Ice env = XCURSOR_SIZE,24 general { # See https://wiki.hyprland.org/Configuring/Variables/ for more gaps_in = 2 gaps_out = 3 border_size = 2 col.active_border = $pink $mauve 45deg col.inactive_border = $surface1 layout = dwindle # Please see https://wiki.hyprland.org/Configuring/Tearing/ before you turn this on # allow_tearing = false } decoration { # See https://wiki.hyprland.org/Configuring/Variables/ for more rounding = 10 blur { enabled = false size = 3 passes = 1 } drop_shadow = false shadow_range = 4 shadow_render_power = 3 col.shadow = rgba(1a1a1aee) } animations { enabled = true # Some default animations, see https://wiki.hyprland.org/Configuring/Animations/ for more bezier = myBezier, 0.05, 0.9, 0.1, 1.05 animation = windows, 1, 3, myBezier animation = windowsOut, 1, 7, default, popin 80% animation = border, 1, 10, default animation = borderangle, 1, 8, default animation = fade, 1, 7, default animation = workspaces, 1, 2.5, default } # misc { # enable_hyprcursor = 1 # } Config File: /home/fox/.config/hypr/themes/frappe.conf: Read Succeeded $rosewaterAlpha = f2d5cf $flamingoAlpha = eebebe $pinkAlpha = f4b8e4 $mauveAlpha = ca9ee6 $redAlpha = e78284 $maroonAlpha = ea999c $peachAlpha = ef9f76 $yellowAlpha = e5c890 $greenAlpha = a6d189 $tealAlpha = 81c8be $skyAlpha = 99d1db $sapphireAlpha = 85c1dc $blueAlpha = 8caaee $lavenderAlpha = babbf1 $textAlpha = c6d0f5 $subtext1Alpha = b5bfe2 $subtext0Alpha = a5adce $overlay2Alpha = 949cbb $overlay1Alpha = 838ba7 $overlay0Alpha = 737994 $surface2Alpha = 626880 $surface1Alpha = 51576d $surface0Alpha = 414559 $baseAlpha = 303446 $mantleAlpha = 292c3c $crustAlpha = 232634 $rosewater = rgba(f5e0dcff) $flamingo = rgba(f2cdcdff) $pink = rgba(f5c2e7ff) $mauve = rgba(cba6f7ff) $red = rgba(f38ba8ff) $maroon = rgba(eba0acff) $peach = rgba(fab387ff) $yellow = rgba(f9e2afff) $green = rgba(a6e3a1ff) $teal = rgba(94e2d5ff) $sky = rgba(89dcebff) $sapphire = rgba(74c7ecff) $blue = rgba(89b4faff) $lavender = rgba(b4befeff) $text = rgba(cdd6f4ff) $subtext1 = rgba(bac2deff) $subtext0 = rgba(a6adc8ff) $overlay2 = rgba(9399b2ff) $overlay1 = rgba(7f849cff) $overlay0 = rgba(6c7086ff) $surface2 = rgba(585b70ff) $surface1 = rgba(45475aff) $surface0 = rgba(313244ff) $base = rgba(1e1e2eff) $mantle = rgba(181825ff) $crust = rgba(11111bff) Config File: /home/fox/.config/hypr/config.d/rules.conf: Read Succeeded # Example windowrule v1 # windowrule = float, ^(kitty)$ # Example windowrule v2 # windowrulev2 = float,class:^(kitty)$,title:^(kitty)$ # See https://wiki.hyprland.org/Configuring/Window-Rules/ for more source = ~/.config/hypr/themes/frappe.conf # Maximize windowrulev2 = bordercolor $sky $blue 45deg, fullscreenstate:1 * # Client Fullscreen Only (fakefullscreen) windowrulev2 = bordercolor $red $red 45deg, fullscreenstate:0 2 windowrulev2 = bordercolor $red $blue $blue $blue $blue $red 45deg, fullscreenstate:1 2 # Maximize + fakefullscreen # Pinned windowrulev2 = bordercolor $yellow 0deg $yellow $maroon 45deg, pinned:1, fullscreenstate:* * # Pinned + fakefullscreen windowrulev2 = bordercolor $red $yellow $yellow $red 45deg $red $yellow $yellow $red 0deg, pinned:1, fullscreenstate:0 2 # Maximize + fakefullscreen # Minimize terminal leftover border for vim workspace = m[DP-3], gapsout:7 # Special Workspace workspace = special:scratchpad, on-created-empty:alacritty # When only 1 tiled window is visible windowrulev2 = noborder, onworkspace:w[tv1] f[-1] s[false], floating:0 windowrulev2 = rounding 0, onworkspace:w[tv1] f[-1] s[false], floating:0 workspace = w[tv1] s[false], gapsout:0 # - fakefullscreen windowrulev2 = noborder off, onworkspace:w[tv1] f[-1], floating:0, fullscreenstate:0 2 # windowrulev2 = bordersize 1, onworkspace:w[tv1] f[-1], floating:0, fullscreenstate:0 2 windowrulev2 = rounding 24, onworkspace:w[tv1] f[-1] m[eDP-1], floating:0, fullscreenstate:0 2 # When only 1 tiled window is visible (maximized) windowrulev2 = bordersize 1, onworkspace:s[false], fullscreenstate:1 * windowrulev2 = rounding 0, onworkspace:s[false], fullscreenstate:1 * windowrulev2 = rounding 24,onworkspace:m[eDP-1] s[false], fullscreenstate:1 * workspace = f[1] s[false], gapsout:0 Config File: /home/fox/.config/hypr/themes/frappe.conf: Read Succeeded $rosewaterAlpha = f2d5cf $flamingoAlpha = eebebe $pinkAlpha = f4b8e4 $mauveAlpha = ca9ee6 $redAlpha = e78284 $maroonAlpha = ea999c $peachAlpha = ef9f76 $yellowAlpha = e5c890 $greenAlpha = a6d189 $tealAlpha = 81c8be $skyAlpha = 99d1db $sapphireAlpha = 85c1dc $blueAlpha = 8caaee $lavenderAlpha = babbf1 $textAlpha = c6d0f5 $subtext1Alpha = b5bfe2 $subtext0Alpha = a5adce $overlay2Alpha = 949cbb $overlay1Alpha = 838ba7 $overlay0Alpha = 737994 $surface2Alpha = 626880 $surface1Alpha = 51576d $surface0Alpha = 414559 $baseAlpha = 303446 $mantleAlpha = 292c3c $crustAlpha = 232634 $rosewater = rgba(f5e0dcff) $flamingo = rgba(f2cdcdff) $pink = rgba(f5c2e7ff) $mauve = rgba(cba6f7ff) $red = rgba(f38ba8ff) $maroon = rgba(eba0acff) $peach = rgba(fab387ff) $yellow = rgba(f9e2afff) $green = rgba(a6e3a1ff) $teal = rgba(94e2d5ff) $sky = rgba(89dcebff) $sapphire = rgba(74c7ecff) $blue = rgba(89b4faff) $lavender = rgba(b4befeff) $text = rgba(cdd6f4ff) $subtext1 = rgba(bac2deff) $subtext0 = rgba(a6adc8ff) $overlay2 = rgba(9399b2ff) $overlay1 = rgba(7f849cff) $overlay0 = rgba(6c7086ff) $surface2 = rgba(585b70ff) $surface1 = rgba(45475aff) $surface0 = rgba(313244ff) $base = rgba(1e1e2eff) $mantle = rgba(181825ff) $crust = rgba(11111bff) Config File: /home/fox/.config/hypr/config.d/keybinds.conf: Read Succeeded # See https://wiki.hyprland.org/Configuring/Keywords/ for more $mainMod = SUPER # # Variables # # Audio Control $sink_volume = pactl get-sink-volume @DEFAULT_SINK@ | grep '^Volume:' | cut -d / -f 2 | tr -d ' ' | sed 's/%//' & $volume_up = pactl set-sink-volume @DEFAULT_SINK@ +5% && $sink_volume $volume_down = pactl set-sink-volume @DEFAULT_SINK@ -5% && $sink_volume $volume_mute = pactl set-sink-mute @DEFAULT_SINK@ toggle && pactl get-sink-mute @DEFAULT_SINK@ | sed -En "/no/ s/.*/$($sink_volume)/p; /yes/ s/.*/0/p" & $volume_mute = pactl set-sink-mute @DEFAULT_SINK@ toggle && pactl get-sink-mute @DEFAULT_SINK@ | sed -En "/no/ s/.*/$($sink_volume)/p; /yes/ s/.*/0/p" & $mic_mute = pactl set-source-mute @DEFAULT_SOURCE@ toggle && pactl get-source-mute @DEFAULT_SOURCE@ | sed -En "/no/ s/.*/$($source_volume)/p; /yes/ s/.*/0/p" & # Brightness Control $brightness_up = brightnessctl -c backlight set +5% $brightness_down = brightnessctl -c backlight set 5%- # # Binds # # TODO: make keybind combination more idomatic # FIX: temp bind = $mainMod SHIFT, O, exec, bash -c "QT_IM_MODULE=wayland telegram-desktop" & bind = $mainMod SHIFT, RETURN, exec, kitty & # Example binds, see https://wiki.hyprland.org/Configuring/Binds/ for more bind = $mainMod, RETURN, exec, alacritty & bind = $mainMod, Q, killactive bind = $mainMod, F, fullscreenstate, 1 1 # Maximize bind = $mainMod SHIFT, F, fullscreenstate, 2 2 # Fullscreen bind = $mainMod CTRL SHIFT, F, fullscreenstate, -1 2 # Fakefullscreen bind = , Print, exec, pidof slurp || grimblast copy area --freeze bind = $mainMod SHIFT, V, togglefloating, bind = $mainMod, V, exec, pkill -15 rofi || cliphist list | rofi -dmenu | cliphist decode | wl-copy bind = $mainMod, P, pseudo # dwindle bind = $mainMod, E, togglesplit # dwindle bind = $mainMod, W, togglegroup bind = $mainMod SHIFT, P, pin, active # Toggle Rofi bindr = $mainMod, Super_L, exec, pkill -15 rofi || ~/.config/rofi/scripts/launcher/launcher.sh & bind = $mainMod, M, exec, pkill -15 rofi || ~/.config/rofi/scripts/powermenu/powermenu.sh & # Launch Apps bind = $mainMod, N, exec, thunar & bind = $mainMod, O, exec, firefox & # Move focus with mainMod + arrow keys bind = $mainMod, left, movefocus, l bind = $mainMod, right, movefocus, r bind = $mainMod, up, movefocus, u bind = $mainMod, down, movefocus, d # Move focus with mainMod + hjkl bind = $mainMod, H, movefocus, l bind = $mainMod, L, movefocus, r bind = $mainMod, K, movefocus, u bind = $mainMod, J, movefocus, d # Switch workspaces with mainMod + [0-9] bind = $mainMod, grave, togglespecialworkspace, scratchpad bind = $mainMod, 1, workspace, 1 bind = $mainMod, 2, workspace, 2 bind = $mainMod, 3, workspace, 3 bind = $mainMod, 4, workspace, 4 bind = $mainMod, 5, workspace, 5 bind = $mainMod, 6, workspace, 6 bind = $mainMod, 7, workspace, 7 bind = $mainMod, 8, workspace, 8 bind = $mainMod, 9, workspace, 9 bind = $mainMod, 0, workspace, 10 # Move active window to a workspace with mainMod + SHIFT + [0-9] bind = $mainMod SHIFT, grave, movetoworkspacesilent, special:scratchpad bind = $mainMod SHIFT, 1, movetoworkspace, 1 bind = $mainMod SHIFT, 2, movetoworkspace, 2 bind = $mainMod SHIFT, 3, movetoworkspace, 3 bind = $mainMod SHIFT, 4, movetoworkspace, 4 bind = $mainMod SHIFT, 5, movetoworkspace, 5 bind = $mainMod SHIFT, 6, movetoworkspace, 6 bind = $mainMod SHIFT, 7, movetoworkspace, 7 bind = $mainMod SHIFT, 8, movetoworkspace, 8 bind = $mainMod SHIFT, 9, movetoworkspace, 9 bind = $mainMod SHIFT, 0, movetoworkspace, 10 # Scroll through existing workspaces with mainMod + scroll bind = $mainMod, mouse_down, workspace, e+1 bind = $mainMod, mouse_up, workspace, e-1 # Move/resize windows with mainMod + LMB/RMB and dragging bindm = $mainMod, mouse:272, movewindow bindm = $mainMod, mouse:273, resizewindow bindm = $mainMod SHIFT, mouse:273, resizewindow 1 # keep window aspect ratio # Move/resize windows with mainMod + Shist + and hjkl bind = $mainMod ALT, H, movewindow, l bind = $mainMod ALT, J, movewindow, d bind = $mainMod ALT, K, movewindow, u bind = $mainMod ALT, L, movewindow, r binde = $mainMod SHIFT, H, resizeactive, -50 0 binde = $mainMod SHIFT, J, resizeactive, 0 50 binde = $mainMod SHIFT, K, resizeactive, 0 -50 binde = $mainMod SHIFT, L, resizeactive, 50 0 # Move current workspace to output -1 bind = $mainMod CTRL SHIFT, H, movecurrentworkspacetomonitor, -1 bind = $mainMod CTRL SHIFT, LEFT, movecurrentworkspacetomonitor, -1 # Move current workspace to output +1 bind = $mainMod CTRL SHIFT, L, movecurrentworkspacetomonitor, +1 bind = $mainMod CTRL SHIFT, RIGHT, movecurrentworkspacetomonitor, +1 # # Trackpad # bind = , XF86TouchpadToggle, exec, ~/.local/scripts/extra/toggle_device DEVICE_TOUCHPAD_ENABLED Touchpad "󰟸 " "󰤳 " & # # Volume # bind = ,XF86AudioRaiseVolume, exec, $volume_up bind = ,XF86AudioLowerVolume, exec, $volume_down bind = ,XF86AudioMute, exec, $volume_mute # # Backlight # bind = ,XF86MonBrightnessUp, exec, $brightness_up bind = ,XF86MonBrightnessDown, exec, $brightness_down # # Global Shortcut # bind = ,F13,pass,^(discord)$ Config File: /home/fox/.config/hypr/config.d/autostart.conf: Read Succeeded # Execute your favorite apps at launch # exec-once = waybar & hyprpaper & firefox # Authentication Agent exec-once=/usr/lib/polkit-kde-authentication-agent-1 & # Clipboard History exec-once = wl-paste --watch cliphist store # bar exec-once = pkill walii-server exec-once = ags & # Notification Daemon exec-once = mako & # Bluetooth Manager exec-once = blueman-applet & # Network Applet exec-once = nm-applet & # Keyd Application Specific Remapping exec-once = keyd-application-mapper -d & # USB auto mount exec-once = udiskie --smart-tray & # Fix ethernet sometime not recognized exec-once = networkctl & 2>&1 > /dev/null ======Config-End======== ```

Description

When switching to wayland from xwayland client, xwayland client doesn't unfocus.

This makes IME not being able to be activated when on the wayland client under these conditions.

  1. When on xwayland, acticvate IME's input method to CJK(or other) and wait a few second.
  2. Switch to wayland without deactivating IME(without switching to english).
  3. Cannot activate input method.

Will do bisect when I have time.

How to reproduce

  1. Open xwayland client and a wayland client.
  2. Click text input on xwayland client
  3. Switch to wayland client

Cursor in xwayland client is still blinking even though the focus is in wayland client.

Crash reports, logs, images, videos

No response

hdm9527 commented 1 month ago

niri has this problem too, but imepopup works fine in xwayland.

Trimutex commented 1 month ago

Agreed as this is a regression, but not from Hyprland itself? Simplest target is Aquamarine but I haven't bisected it yet to be able to fully pinpoint the problem. Confirmed not by Hyprland by testing #7458 which I've seen handle this case specifically.

sungyoonc commented 1 month ago

Hi @Trimutex. May I ask why g_pCompositor->m_pLastWindow && !g_pCompositor->m_pLastWindow->m_bIsX11 is here in #7458 ?

// In activateSurface()
if (!surf || (!activate && g_pCompositor->m_pLastWindow && !g_pCompositor->m_pLastWindow->m_bIsX11)) {

Because, I think it directly clashes with unfocusing part(when switching focus from xwayland to wayland) here

            if (g_pCompositor->m_pLastFocus && g_pCompositor->m_pLastWindow->m_bIsX11)
                activateSurface(g_pCompositor->m_pLastFocus.lock(), false);
Trimutex commented 1 month ago

Yeah so the naming gets a bit messy when working with the focus function here. If the last surface (current one we are trying to focus) is not x11, but the old focus (before function call) is, we want to focus nothing in xwayland.

JohnOberhauser commented 1 month ago

I think it's probably the same issue: When switching to a wayland client from Intellij Idea, the auto save function doesn't work. It does seem to work if I switch to another xwayland client though. I started noticing this recently.

sungyoonc commented 1 month ago

Yeah so the naming gets a bit messy when working with the focus function here. If the last surface (current one we are trying to focus) is not x11, but the old focus (before function call) is, we want to focus nothing in xwayland.

In here

void CXWM::activateSurface(SP<CXWaylandSurface> surf, bool activate) {
    if ((surf == focusedSurface && activate) || (surf && surf->overrideRedirect))
        return;

    if (!surf || (!activate && g_pCompositor->m_pLastWindow && !g_pCompositor->m_pLastWindow->m_bIsX11)) {
        setActiveWindow((uint32_t)XCB_WINDOW_NONE);
        focusWindow(nullptr);
    } else {
        setActiveWindow(surf ? surf->xID : (uint32_t)XCB_WINDOW_NONE);
        focusWindow(surf);
    }

    xcb_flush(connection);
}

Doesn't this !g_pCompositor->m_pLastWindow->m_bIsX11 should be this g_pCompositor->m_pLastWindow->m_bIsX11 (without the !)?

If m_pLastWindow->m_bIsX11 is true in CHyprXWaylandManager::activateSurface, it then it results in CXWM::activateSurface(surf, false) being called. However the if statement in CXWM::activateSurface wants activate to be false and m_pLastWindow->m_bIsX11 to be false. Because of this the if statement doesn't pass and focusWindow(surf); is called instead of focusWindow(nullptr);.

// In CHyprXWaylandManager::activateSurface()
if (g_pCompositor->m_pLastFocus && g_pCompositor->m_pLastWindow->m_bIsX11)
    activateSurface(g_pCompositor->m_pLastFocus.lock(), false);

Am I understanding it right?

Trimutex commented 1 month ago

m_pLastWindow != m_pLastFocus when switching the surface focus using g_pCompositor->focusSurface() after g_pCompositor->focusWindow().

m_pLastWindow is the new current window while m_pLastFocus is the previously focused surface. As such we are double checking that the current window is not X11 and XWayland should clear its focus.

Feel free to test and PR if you find this to be the issue though or have a better method.

Trimutex commented 1 month ago

Going to give bisecting Aquamarine a go. Will update

Trimutex commented 1 month ago

Interestingly it seems to have never actually unfocused when going back on these commits when downgrading other pieces? I recall testing it and confirming it unfocused when I made the commit but I can't reproduce it anymore.

Anyway, you were on the right track with the troublesome code piece. The test should have been for the focus's window, not the last global window. On a second look this piece brings the XWM focus back to that surface. Putting up a PR now :)