Keep the games workspace on the HDMI screen

Wine games lose the mouse when their window moves between screens. safeView replaces greedyView for mod-N, xmobar clicks and mpv so workspace 3 always opens on screen 0 and is never swapped away; safeRescreen keeps a hidden workspace 3 off the laptop screen when screens change.
This commit is contained in:
Daniele Fucini
2026-10-24 20:27:52 +02:00
parent b10970bf36
commit 3e5824a590
+30 -3
View File
@@ -4,6 +4,7 @@ import Data.Monoid
import Graphics.X11.ExtraTypes.XF86 import Graphics.X11.ExtraTypes.XF86
import Control.Monad (forM_, liftM2, when) import Control.Monad (forM_, liftM2, when)
import XMonad import XMonad
import XMonad.Actions.OnScreen (greedyViewOnScreen)
import XMonad.Actions.PhysicalScreens import XMonad.Actions.PhysicalScreens
import XMonad.Hooks.EwmhDesktops import XMonad.Hooks.EwmhDesktops
import XMonad.Hooks.ManageDocks import XMonad.Hooks.ManageDocks
@@ -34,10 +35,10 @@ main :: IO ()
main = main =
xmonad xmonad
. ewmhFullscreen . ewmhFullscreen
. setEwmhSwitchDesktopHook W.greedyView . setEwmhSwitchDesktopHook safeView
. ewmh . ewmh
. docks . docks
. addAfterRescreenHook restartStatusBars . rescreenHook def {afterRescreenHook = restartStatusBars, rescreenWorkspacesHook = Last (Just safeRescreen)}
. addRandrChangeHook (spawn myScreenHotplug) . addRandrChangeHook (spawn myScreenHotplug)
$ myConfig $ myConfig
@@ -145,6 +146,32 @@ myConfig =
| (key, sc) <- zip [xK_w, xK_e] [0 ..], | (key, sc) <- zip [xK_w, xK_e] [0 ..],
(f, mask) <- [(viewScreen def, 0), (sendToScreen def, shiftMask)] (f, mask) <- [(viewScreen def, 0), (sendToScreen def, shiftMask)]
] ]
++ [((myModMask, key), windows $ safeView ws) | (ws, key) <- zip myWorkspaces [xK_1 .. xK_9]]
-- greedyView that keeps wsGames on screen 0 (HDMI): Wine games lose the mouse when moved between screens
safeView :: WorkspaceId -> WindowSet -> WindowSet
safeView i ws
| i == wsGames = greedyViewOnScreen 0 i ws
| W.currentTag ws == wsGames && i `elem` map (W.tag . W.workspace) (W.visible ws) = W.view i ws
| otherwise = W.greedyView i ws
-- xmonad's rescreen, except that a hidden wsGames is never put on a secondary screen
safeRescreen :: X ()
safeRescreen = do
screens <- withDisplay getCleanedScreenInfo
case screens of
[] -> return ()
xinesc : xinescs ->
windows $ \ws ->
let notGames = (/= wsGames) . W.tag
pool = map W.workspace (W.visible ws) ++ filter notGames (W.hidden ws)
(xs, _) = splitAt (length xinescs) pool
shown = map W.tag (W.workspace (W.current ws) : xs)
in ws
{ W.current = W.Screen (W.workspace (W.current ws)) 0 (SD xinesc),
W.visible = zipWith3 W.Screen xs [1 ..] (map SD xinescs),
W.hidden = filter ((`notElem` shown) . W.tag) (map W.workspace (W.visible ws) ++ W.hidden ws)
}
-- Workspaces -- Workspaces
myWorkspaces :: [String] myWorkspaces :: [String]
@@ -291,7 +318,7 @@ myManageHook =
isFullscreen --> doFullFloat isFullscreen --> doFullFloat
] ]
<+> namedScratchpadManageHook myScratchpads <+> namedScratchpadManageHook myScratchpads
where viewShift = doF . liftM2 (.) W.greedyView W.shift where viewShift = doF . liftM2 (.) safeView W.shift
-- Handle event hook -- Handle event hook
myHandleEventHook :: Event -> X All myHandleEventHook :: Event -> X All