From 5f1cea7f2544da57c5e7cae886f6a064e1c2beab Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9ana=20=E6=B1=9F?= Date: Mon, 17 Nov 2025 08:31:01 +0800 Subject: [PATCH] vanadium/xmonad: shift windows based on dynamic title property --- .../vanadium/home/xmonad/xmonad.hs | 28 +++++++++++++++++++ 1 file changed, 28 insertions(+) diff --git a/nix/configurations/vanadium/home/xmonad/xmonad.hs b/nix/configurations/vanadium/home/xmonad/xmonad.hs index 3c3ad491..898245aa 100644 --- a/nix/configurations/vanadium/home/xmonad/xmonad.hs +++ b/nix/configurations/vanadium/home/xmonad/xmonad.hs @@ -8,6 +8,7 @@ import XMonad.Hooks.EwmhDesktops import XMonad.Hooks.InsertPosition import XMonad.Hooks.ManageDocks import XMonad.Hooks.ManageHelpers +import XMonad.Hooks.OnPropertyChange import XMonad.Hooks.RefocusLast import XMonad.Hooks.StatusBar import XMonad.Layout.NoBorders @@ -25,6 +26,7 @@ import XMonad.Util.SpawnOnce import XMonad.Layout.Magnifier import Data.Char.Greek +import Data.Semigroup import qualified Data.Map.Strict as M import System.Posix import Graphics.X11.ExtraTypes.XF86 @@ -50,6 +52,7 @@ main = , startupHook = myStartupHook , layoutHook = myLayout , manageHook = myManageHook + , handleEventHook = myEventHandleHook } -- Only remove mappings that needs pass through @@ -81,6 +84,9 @@ isEvolution = className ~? "gnome.Evolution" isFirefox :: Query Bool isFirefox = className =? "firefox" +isSpotify :: Query Bool +isSpotify = isFirefox <&&> title ~? "Spotify" + isFirefoxPip :: Query Bool isFirefoxPip = isFirefox <&&> title =? "Picture-in-Picture" @@ -127,6 +133,25 @@ myManageHook = ] <> namedScratchpadManageHook myScratchpads +myEventHandleHook :: Event -> X All +myEventHandleHook = + -- TODO: is there a way to always open certain sites in new windows in firefox? + onTitleChange $ composeAll + [ isSpotify --> doShiftAndViewIfMoved multimediaWS + , isDiscord --> doShiftAndViewIfMoved chatWS + ] + +-- If the title changes in the background, we don't want to greedy view that workspace. +-- Imagine Spotify playing in the background, a track change would focus that workspace. +-- We prevent this by checking if the window is already there. +doShiftAndViewIfMoved :: WorkspaceId -> Query (Endo WindowSet) +doShiftAndViewIfMoved n = doF . shiftAndViewIfMoved n =<< ask + +shiftAndViewIfMoved :: WorkspaceId -> Window -> WindowSet -> WindowSet +shiftAndViewIfMoved n w s = case W.findTag w s of + Just from | n `W.tagMember` s && n /= from -> W.greedyView n $ W.shiftWin n w s + _ -> s + myStartupHook :: X () myStartupHook = do spawnOnce "fcitx5 &" -- Input method @@ -261,6 +286,9 @@ altMask = mod1Mask myWorkspaces :: [WorkspaceId] myWorkspaces = map (:[]) $ take 8 greekLower +multimediaWS :: WorkspaceId +multimediaWS = myWorkspaces !! 6 + chatWS :: WorkspaceId chatWS = myWorkspaces !! 3