Fix window swallowing problems in xmonad

This commit is contained in:
Leon Kowarschick 2020-07-06 13:45:59 +02:00
parent 716d57797b
commit 20a68552c1
2 changed files with 36 additions and 16 deletions

View file

@ -23,9 +23,9 @@ import qualified XMonad.Util.ExtensibleState as XS
import qualified Rofi import qualified Rofi
import qualified DescribedSubmap import qualified DescribedSubmap
import qualified TiledDragging import qualified TiledDragging
--import qualified WindowSwallowing import qualified WindowSwallowing
import XMonad.Hooks.WindowSwallowing as WindowSwallowing --import XMonad.Hooks.WindowSwallowing as WindowSwallowing
import Data.Foldable ( for_ ) import Data.Foldable ( for_ )

View file

@ -44,11 +44,14 @@ where
import XMonad import XMonad
import qualified XMonad.StackSet as W import qualified XMonad.StackSet as W
import qualified XMonad.Util.ExtensibleState as XS import qualified XMonad.Util.ExtensibleState as XS
import XMonad.Util.Run ( runProcessWithInput ) import XMonad.Util.Run ( runProcessWithInput
, safeSpawn
)
import XMonad.Util.WindowProperties import XMonad.Util.WindowProperties
import Data.Semigroup ( All(..) ) import Data.Semigroup ( All(..) )
import qualified Data.Map.Strict as M import qualified Data.Map.Strict as M
import Data.List ( isInfixOf ) import Data.List ( isInfixOf )
import Data.Maybe ( fromMaybe )
import Control.Monad ( when ) import Control.Monad ( when )
-- $usage -- $usage
@ -58,7 +61,7 @@ import Control.Monad ( when )
-- --
-- and using 'swallowEventHook' somewhere in your 'handleEventHook', for example: -- and using 'swallowEventHook' somewhere in your 'handleEventHook', for example:
-- --
-- > myHandleEventHook = swallowEventHook [className =? "Alacritty", className =? "Termite"] [return True] -- > myHandleEventHook = swallowEventHook (className =? "Alacritty" <||> className =? "Termite") (return True)
-- --
-- For more information on editing your handleEventHook and key bindings, -- For more information on editing your handleEventHook and key bindings,
-- see "XMonad.Doc.Extending". -- see "XMonad.Doc.Extending".
@ -117,6 +120,7 @@ swallowEventHook parentQueries childQueries event = do
XS.modify . setStackBeforeWindowClosing . currentStack $ ws XS.modify . setStackBeforeWindowClosing . currentStack $ ws
XS.modify . setFloatingBeforeWindowClosing . W.floating $ ws XS.modify . setFloatingBeforeWindowClosing . W.floating $ ws
-- This is called right after any window closes. -- This is called right after any window closes.
DestroyWindowEvent { ev_event = eventId, ev_window = childWindow } -> DestroyWindowEvent { ev_event = eventId, ev_window = childWindow } ->
-- Because DestroyWindowEvent is emitted a lot more often then you think, -- Because DestroyWindowEvent is emitted a lot more often then you think,
@ -130,17 +134,33 @@ swallowEventHook parentQueries childQueries event = do
case (maybeSwallowedParent, maybeOldStack) of case (maybeSwallowedParent, maybeOldStack) of
(Just parent, Just oldStack) -> do (Just parent, Just oldStack) -> do
-- If there actually is a corresponding swallowed parent window for this window, -- If there actually is a corresponding swallowed parent window for this window,
-- we will restore and place it where the closed window was. -- we will try to restore it.
-- For this, we look at the stack-state that was stored /before/ the window was closed, -- because there are some cases where the stack-state is not stored correctly in the ConfigureEvent hook,
-- and replace the focused window with the now restored parent. -- we have to first check if the stack-state is valid.
-- we do this to make sure the parent is restored in the exact position the child was at. -- if it is, we can restore the parent exactly where the child window was before being closed
windows -- if the stored stack-state is invalid however, we still restore the window
(\ws -> -- by just inserting it as the focused window in the stack.
updateCurrentStack stackStoredCorrectly <- do
(const $ Just $ oldStack { W.focus = parent }) curStack <- withWindowSet (return . currentStack)
$ moveFloatingState childWindow parent let oldLen = length (W.integrate oldStack)
$ ws { W.floating = oldFloating } let curLen = length (W.integrate' curStack)
) return (oldLen - 1 == curLen && childWindow == W.focus oldStack)
if stackStoredCorrectly
then windows
(\ws ->
updateCurrentStack
(const $ Just $ oldStack { W.focus = parent })
$ moveFloatingState childWindow parent
$ ws { W.floating = oldFloating }
)
else windows
(W.modify
(Just $ W.Stack parent [] [])
(\s -> Just
$ s { W.focus = parent, W.down = W.focus s : W.down s }
)
)
-- after restoring, we remove the information about the swallowing from the state. -- after restoring, we remove the information about the swallowing from the state.
XS.modify $ removeSwallowed childWindow XS.modify $ removeSwallowed childWindow
XS.modify $ setStackBeforeWindowClosing Nothing XS.modify $ setStackBeforeWindowClosing Nothing
@ -149,7 +169,6 @@ swallowEventHook parentQueries childQueries event = do
_ -> return () _ -> return ()
return $ All True return $ All True
-- | run a pure transformation on the Stack of the currently focused workspace. -- | run a pure transformation on the Stack of the currently focused workspace.
updateCurrentStack updateCurrentStack
:: (Maybe (W.Stack a) -> Maybe (W.Stack a)) :: (Maybe (W.Stack a) -> Maybe (W.Stack a))
@ -223,3 +242,4 @@ instance ExtensionClass SwallowingState where
fi :: (Integral a, Num b) => a -> b fi :: (Integral a, Num b) => a -> b
fi = fromIntegral fi = fromIntegral