mirror of
https://github.com/elkowar/dots-of-war.git
synced 2024-12-24 13:22:23 +00:00
asdf
This commit is contained in:
parent
d071db1afa
commit
4e64f432c9
6 changed files with 144 additions and 43 deletions
|
@ -1,4 +1,4 @@
|
|||
{
|
||||
"optOut": false,
|
||||
"lastUpdateCheck": 1592553121962
|
||||
"lastUpdateCheck": 1592658266558
|
||||
}
|
|
@ -4,11 +4,11 @@ mode=5
|
|||
bgcolor=#000000
|
||||
|
||||
[xin_0]
|
||||
file=/home/leon/Bilder/wallpapers/abstract-barb-wires-blur-close-up-116021.jpg
|
||||
file=/home/leon/Bilder/wallpapers/green_leaves.jpg
|
||||
mode=5
|
||||
bgcolor=#000000
|
||||
|
||||
[xin_1]
|
||||
file=/home/leon/Bilder/wallpapers/abstract-barb-wires-blur-close-up-116021.jpg
|
||||
file=/home/leon/Bilder/wallpapers/green_leaves.jpg
|
||||
mode=5
|
||||
bgcolor=#000000
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
[geometry]
|
||||
posx=20
|
||||
posy=50
|
||||
sizex=1432
|
||||
sizey=841
|
||||
sizex=1297
|
||||
sizey=696
|
||||
|
||||
[nitrogen]
|
||||
view=icon
|
||||
|
|
Binary file not shown.
|
@ -23,9 +23,9 @@ import qualified XMonad.Util.ExtensibleState as XS
|
|||
import qualified Rofi
|
||||
import qualified DescribedSubmap
|
||||
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_ )
|
||||
|
@ -444,6 +444,8 @@ myKeys = concat [ zoomRowBindings, tabbedBindings, multiMonitorBindings, program
|
|||
, ("Kill all other copies", killAllOtherCopies)
|
||||
, ("toggle polybar", sendMessage ToggleStruts >> safeSpawn "polybar-msg" ["cmd", "toggle"])
|
||||
, ("get debug data", debugStackFullString >>= (\str -> safeSpawn "xmessage" [str]))
|
||||
, ("get full stackset", withWindowSet (\ws -> spawn $ "echo '" ++ show (W.floating ws) ++ "\n" ++ show (W.current ws) ++ "' | xclip -in -selection clipboard"))
|
||||
, ("asdf", windows (\ws -> ws {W.floating = M.empty }))
|
||||
]
|
||||
|
||||
|
||||
|
@ -522,7 +524,7 @@ main = do
|
|||
-- }}}
|
||||
|
||||
|
||||
mySwallowEventHook = WindowSwallowing.swallowEventHook [className =? "Alacritty", className =? "Termite", className =? "Thunar"] [return True]
|
||||
mySwallowEventHook = WindowSwallowing.swallowEventHook (className =? "Alacritty" <||> className =? "Termite" <||> className =? "Thunar") (return True)
|
||||
|
||||
|
||||
activateWindowEventHook :: Event -> X All
|
||||
|
@ -531,7 +533,11 @@ activateWindowEventHook (ClientMessageEvent { ev_message_type = messageType, ev_
|
|||
when (messageType == activateWindowAtom) $
|
||||
if window `elem` (concatMap (W.integrate' . W.stack . W.workspace) (W.current ws : W.visible ws))
|
||||
then windows (W.focusWindow window)
|
||||
else windows (W.shiftWin (W.tag $ W.workspace $ W.current ws) window)
|
||||
else do
|
||||
shouldRaise <- runQuery (className =? "discord" <||> className =? "web.whatsapp.com") window
|
||||
if shouldRaise
|
||||
then windows (W.shiftWin (W.tag $ W.workspace $ W.current ws) window)
|
||||
else windows (W.focusWindow window)
|
||||
return $ All True
|
||||
activateWindowEventHook _ = return $ All True
|
||||
|
||||
|
|
|
@ -1,4 +1,42 @@
|
|||
{-# LANGUAGE NamedFieldPuns #-}
|
||||
-----------------------------------------------------------------------------
|
||||
-- |
|
||||
-- Module : XMonad.Hooks.WindowSwallowing
|
||||
-- Copyright : (c) 2020 Leon Kowarschick
|
||||
-- License : BSD3-style (see LICENSE)
|
||||
--
|
||||
-- Maintainer : Leon Kowarschick. <thereal.elkowar@gmail.com>
|
||||
-- Stability : unstable
|
||||
-- Portability : unportable
|
||||
--
|
||||
-- Provides a handleEventHook that implements window swallowing.
|
||||
--
|
||||
-- If you open a GUI-window (i.e. feh) from the terminal,
|
||||
-- the terminal will normally still be shown on screen, unnecessarily
|
||||
-- taking up space on the screen.
|
||||
-- With window swallowing, can detect that you opened a window from within another
|
||||
-- window, and allows you "swallow" that parent window for the time the new
|
||||
-- window is running.
|
||||
--
|
||||
-- __NOTE__: This module depends on @pstree@ to analyze the process hierarchy, so make
|
||||
-- sure that is on your @$PATH@.
|
||||
--
|
||||
-- __NOTE__ that this does not always work perfectly:
|
||||
--
|
||||
-- - Because window swallowing needs to check the process hierarchy, it requires
|
||||
-- both the child and the parent to be distinct processes. This means that
|
||||
-- applications which implement instance sharing cannot be supported by window swallowing.
|
||||
-- Most notably, this excludes some terminal emulators as well as tmux
|
||||
-- from functioning as the parent process. It also excludes a good amount of
|
||||
-- child programs, because many graphical applications do implement instance sharing.
|
||||
-- For example, window swallowing will probably not work with your browser.
|
||||
--
|
||||
-- - To check the process hierarchy, we need to be able to get the process ID
|
||||
-- by looking at the window. This requires the @_NET_WM_PID@ X-property to be set.
|
||||
-- If any application you want to use this with does not provide the @_NET_WM_PID@,
|
||||
-- there is not much you can do except for reaching out to the author of that
|
||||
-- application and asking them to set that property.
|
||||
-----------------------------------------------------------------------------
|
||||
module WindowSwallowing
|
||||
( swallowEventHook
|
||||
)
|
||||
|
@ -12,24 +50,94 @@ import Data.Semigroup ( All(..) )
|
|||
import qualified Data.Map.Strict as M
|
||||
import Data.List ( isInfixOf )
|
||||
import Control.Monad ( when )
|
||||
import qualified XMonad.Layout.Hidden as Hidden
|
||||
|
||||
-- $usage
|
||||
-- You can use this module by including the following in your @~\/.xmonad/xmonad.hs@:
|
||||
--
|
||||
-- > import XMonad.Hooks.WindowSwallowing
|
||||
--
|
||||
-- and using 'swallowEventHook' somewhere in your 'handleEventHook', for example:
|
||||
--
|
||||
-- > myHandleEventHook = swallowEventHook [className =? "Alacritty", className =? "Termite"] [return True]
|
||||
--
|
||||
-- For more information on editing your handleEventHook and key bindings,
|
||||
-- see "XMonad.Doc.Extending".
|
||||
|
||||
|
||||
swallowEventHook :: [Query Bool] -> [Query Bool] -> Event -> X All
|
||||
-- | handleEventHook that will swallow child windows when they are
|
||||
-- opened from another window.
|
||||
swallowEventHook
|
||||
:: Query Bool -- ^ query the parent window has to match for window swallowing to occur.
|
||||
-- Set this to @return True@ to run swallowing for every parent.
|
||||
-> Query Bool -- ^ query the child window has to match for window swallowing to occur.
|
||||
-- Set this to @return True@ to run swallowing for every child
|
||||
-> Event -- ^ The event to handle.
|
||||
-> X All
|
||||
swallowEventHook parentQueries childQueries event = do
|
||||
case event of
|
||||
-- This is called right before a window gets opened. We intercept that
|
||||
-- call to possibly open the window ourselves, swapping out
|
||||
-- it's parent processes window for the new window in the stack.
|
||||
MapRequestEvent { ev_window = childWindow } ->
|
||||
-- For a window to be opened from within another window, that other window
|
||||
-- must be focused. Thus the parent window that would be swallowed has to be
|
||||
-- the currently focused window.
|
||||
withFocused $ \parentWindow -> do
|
||||
-- First verify that both windows match the given queries
|
||||
parentMatches <- runQuery parentQueries parentWindow
|
||||
childMatches <- runQuery childQueries childWindow
|
||||
when (parentMatches && childMatches) $ do
|
||||
-- read the windows _NET_WM_PID properties
|
||||
childWindowPid <- getProp32s "_NET_WM_PID" childWindow
|
||||
parentWindowPid <- getProp32s "_NET_WM_PID" parentWindow
|
||||
case (parentWindowPid, childWindowPid) of
|
||||
(Just (parentPid : _), Just (childPid : _)) -> do
|
||||
-- check if the new window is a child process of the last focused window
|
||||
-- using the process ids.
|
||||
isChild <- liftIO $ fi childPid `isChildOf` fi parentPid
|
||||
when isChild $ do
|
||||
-- We set the newly opened window as the focused window, replacing the parent window.
|
||||
-- If the parent window was floating, we transfer that data to the child,
|
||||
-- such that it shows up at the same position, with the same dimensions.
|
||||
|
||||
windows
|
||||
( W.modify' (\x -> x { W.focus = childWindow })
|
||||
. copyFloatingState parentWindow childWindow
|
||||
)
|
||||
windows
|
||||
(\ws ->
|
||||
ws { W.floating = M.delete parentWindow (W.floating ws) }
|
||||
)
|
||||
XS.modify (addSwallowedParent parentWindow childWindow)
|
||||
_ -> return ()
|
||||
return ()
|
||||
|
||||
|
||||
-- This is called in many circumstances, most notably for us:
|
||||
-- right before a window gets closed. We store the current
|
||||
-- state of the window stack here, such that we know where the
|
||||
-- child window was on the screen when restoring the swallowed parent process.
|
||||
ConfigureEvent{} -> withWindowSet $ \ws -> do
|
||||
XS.modify . setStackBeforeWindowClosing . currentStack $ ws
|
||||
XS.modify . setFloatingBeforeWindowClosing . W.floating $ ws
|
||||
|
||||
-- This is called right after any window closes.
|
||||
DestroyWindowEvent { ev_event = eventId, ev_window = childWindow } ->
|
||||
-- Because DestroyWindowEvent is emitted a lot more often then you think,
|
||||
-- this check verifies that the event is /actually/ about closing a window.
|
||||
when (eventId == childWindow) $ do
|
||||
-- we get some data from the extensible state, most notably we ask for
|
||||
-- the \"parent\" window of the now closed window.
|
||||
maybeSwallowedParent <- XS.gets (getSwallowedParent childWindow)
|
||||
maybeOldStack <- XS.gets stackBeforeWindowClosing
|
||||
oldFloating <- XS.gets floatingBeforeClosing
|
||||
case (maybeSwallowedParent, maybeOldStack) of
|
||||
(Just parent, Just oldStack) -> do
|
||||
--Hidden.popHiddenWindow parent
|
||||
-- If there actually is a corresponding swallowed parent window for this window,
|
||||
-- we will restore and place it where the closed window was.
|
||||
-- For this, we look at the stack-state that was stored /before/ the window was closed,
|
||||
-- and replace the focused window with the now restored parent.
|
||||
-- we do this to make sure the parent is restored in the exact position the child was at.
|
||||
windows
|
||||
(\ws ->
|
||||
updateCurrentStack
|
||||
|
@ -37,50 +145,36 @@ swallowEventHook parentQueries childQueries event = do
|
|||
$ copyFloatingState childWindow parent
|
||||
$ ws { W.floating = oldFloating }
|
||||
)
|
||||
windows
|
||||
(\ws -> ws { W.floating = M.delete childWindow (W.floating ws) })
|
||||
|
||||
-- after restoring, we remove the information about the swallowing from the state.
|
||||
XS.modify $ removeSwallowed childWindow
|
||||
XS.modify $ setStackBeforeWindowClosing Nothing
|
||||
_ -> return ()
|
||||
return ()
|
||||
|
||||
MapRequestEvent { ev_window = childWindow } ->
|
||||
withFocused $ \parentWindow -> do
|
||||
parentMatches <- mapM (`runQuery` parentWindow) parentQueries
|
||||
childMatches <- mapM (`runQuery` childWindow) childQueries
|
||||
when (or parentMatches && or childMatches) $ do
|
||||
childWindowPid <- getProp32s "_NET_WM_PID" childWindow
|
||||
parentWindowPid <- getProp32s "_NET_WM_PID" parentWindow
|
||||
case (parentWindowPid, childWindowPid) of
|
||||
(Just (parentPid : _), Just (childPid : _)) -> do
|
||||
isChild <- liftIO $ fi childPid `isChildOf` fi parentPid
|
||||
when isChild $ do
|
||||
windows
|
||||
(updateCurrentStack (fmap (\x -> x { W.focus = childWindow }))
|
||||
. copyFloatingState parentWindow childWindow
|
||||
)
|
||||
XS.modify (addSwallowedParent parentWindow childWindow)
|
||||
--Hidden.hideWindow parentWindow
|
||||
_ -> return ()
|
||||
return ()
|
||||
_ -> return ()
|
||||
return $ All True
|
||||
|
||||
|
||||
-- | run a pure transformation on the Stack of the currently focused workspace.
|
||||
updateCurrentStack
|
||||
:: (Maybe (W.Stack a) -> Maybe (W.Stack a))
|
||||
-> W.StackSet i l a sid sd
|
||||
-> W.StackSet i l a sid sd
|
||||
updateCurrentStack f ws = ws
|
||||
{ W.current = (W.current ws)
|
||||
{ W.workspace = currentWsp { W.stack = f $ currentStack ws }
|
||||
}
|
||||
}
|
||||
where currentWsp = W.workspace $ W.current ws
|
||||
updateCurrentStack f = W.modify (f Nothing) (f . Just)
|
||||
|
||||
currentStack :: W.StackSet i l a sid sd -> Maybe (W.Stack a)
|
||||
currentStack = W.stack . W.workspace . W.current
|
||||
|
||||
|
||||
-- | copy the floating related state of one window to another window in a StackSet.
|
||||
copyFloatingState
|
||||
:: Ord a => a -> a -> W.StackSet i l a s sd -> W.StackSet i l a s sd
|
||||
:: Ord a
|
||||
=> a -- ^ window to copy from
|
||||
-> a -- ^ window to copy to
|
||||
-> W.StackSet i l a s sd
|
||||
-> W.StackSet i l a s sd
|
||||
copyFloatingState from to ws = ws
|
||||
{ W.floating = maybe (M.delete to (W.floating ws))
|
||||
(\r -> M.insert to r (W.floating ws))
|
||||
|
@ -135,3 +229,4 @@ instance ExtensionClass SwallowingState where
|
|||
|
||||
fi :: (Integral a, Num b) => a -> b
|
||||
fi = fromIntegral
|
||||
|
||||
|
|
Loading…
Reference in a new issue