diff --git a/CHANGES.md b/CHANGES.md index 85f6293f..27a3f9f9 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -64,11 +64,18 @@ - Flipped how `(^?)`, `(~?)`, and `($?)` work to more accurately reflect how one uses these operators. + - Added `isMinimized` + * `XMonad.Actions.WindowNavigation` - Fixed navigation getting "stuck" in certain situations for widescreen resolutions. + * `XMonad.Layout.BinarySpacePartition` + + - Hidden windows are now ignored by the layout so that hidden windows in + the stack don't offset position calculations in the layout. + * `XMonad.Layout.MagicFocus` - The focused window will always be at the master area in the stack being diff --git a/XMonad/Hooks/ManageHelpers.hs b/XMonad/Hooks/ManageHelpers.hs index 3f9dbac3..0d211084 100644 --- a/XMonad/Hooks/ManageHelpers.hs +++ b/XMonad/Hooks/ManageHelpers.hs @@ -49,6 +49,7 @@ module XMonad.Hooks.ManageHelpers ( isInProperty, isKDETrayWindow, isFullscreen, + isMinimized, isDialog, pid, transientTo, @@ -183,6 +184,11 @@ isInProperty p v = ask >>= \w -> liftX $ do isFullscreen :: Query Bool isFullscreen = isInProperty "_NET_WM_STATE" "_NET_WM_STATE_FULLSCREEN" +-- | A predicate to check whether a window is hidden (minimized). +-- See also "XMonad.Actions.Minimize". +isMinimized :: Query Bool +isMinimized = isInProperty "_NET_WM_STATE" "_NET_WM_STATE_HIDDEN" + -- | A predicate to check whether a window is a dialog. isDialog :: Query Bool isDialog = isInProperty "_NET_WM_WINDOW_TYPE" "_NET_WM_WINDOW_TYPE_DIALOG" diff --git a/XMonad/Layout/BinarySpacePartition.hs b/XMonad/Layout/BinarySpacePartition.hs index f829b808..1966ccd2 100644 --- a/XMonad/Layout/BinarySpacePartition.hs +++ b/XMonad/Layout/BinarySpacePartition.hs @@ -38,6 +38,7 @@ module XMonad.Layout.BinarySpacePartition ( import XMonad import XMonad.Prelude hiding (insert) import qualified XMonad.StackSet as W +import XMonad.Hooks.ManageHelpers (isMinimized) import XMonad.Util.Stack hiding (Zipper) import XMonad.Util.Types @@ -696,20 +697,23 @@ replaceFloating wsm = do getFloating :: X [Window] getFloating = M.keys . W.floating <$> gets windowset -- all floating windows +getHidden :: X [Window] +getHidden = getStackSet >>= filterM (runQuery isMinimized) . W.integrate' + getStackSet :: X (Maybe (W.Stack Window)) getStackSet = W.stack . W.workspace . W.current <$> gets windowset -- windows on this WS (with floating) getScreenRect :: X Rectangle getScreenRect = screenRect . W.screenDetail . W.current <$> gets windowset -withoutFloating :: [Window] -> Maybe (W.Stack Window) -> Maybe (W.Stack Window) -withoutFloating fs = maybe Nothing (unfloat fs) +withoutFloating :: [Window] -> [Window] -> Maybe (W.Stack Window) -> Maybe (W.Stack Window) +withoutFloating fs hs = maybe Nothing (unfloat fs hs) -- ignore messages if current focus is on floating window, otherwise return stack without floating -unfloat :: [Window] -> W.Stack Window -> Maybe (W.Stack Window) -unfloat fs s = if W.focus s `elem` fs +unfloat :: [Window] -> [Window] -> W.Stack Window -> Maybe (W.Stack Window) +unfloat fs hs s = if W.focus s `elem` fs then Nothing - else Just $ s{W.up = W.up s \\ fs, W.down = W.down s \\ fs} + else Just $ s{W.up = W.up s \\ (fs ++ hs), W.down = W.down s \\ (fs ++ hs)} instance LayoutClass BinarySpacePartition Window where doLayout b r s = do @@ -743,9 +747,10 @@ instance LayoutClass BinarySpacePartition Window where | otherwise = do ws <- getStackSet fs <- getFloating + hs <- getHidden r <- getScreenRect -- removeBorder $ refWins $ getSelectedNode b - let lws = withoutFloating fs ws -- tiled windows on WS + let lws = withoutFloating fs hs ws -- tiled windows on WS lfs = maybe [] W.integrate ws \\ maybe [] W.integrate lws -- untiled windows on WS b' = handleMesg r -- transform tree (concerns only tiled windows) ws' = adjustStack ws lws lfs b' -- apply transformation to window stack, reintegrate floating wins @@ -783,6 +788,7 @@ handleResize :: BinarySpacePartition Window -> WindowArrangerMsg -> X (Maybe (Bi handleResize b (SetGeometry newrect@(Rectangle _ _ w h)) = do ws <- getStackSet fs <- getFloating + hs <- getHidden case W.focus <$> ws of Nothing -> return Nothing Just win -> do @@ -791,7 +797,7 @@ handleResize b (SetGeometry newrect@(Rectangle _ _ w h)) = do let (xsc,ysc) = (fi w % fi ow, fi h % fi oh) (xsc',ysc') = (rough xsc, rough ysc) dirs = changedDirs oldrect newrect (fi mx,fi my) - n = elemIndex win $ maybe [] W.integrate $ withoutFloating fs ws + n = elemIndex win $ maybe [] W.integrate $ withoutFloating fs hs ws -- unless (isNothing dir) $ debug $ -- show (fi x-fi ox,fi y-fi oy) ++ show (fi w-fi ow,fi h-fi oh) -- ++ show dir ++ " " ++ show win ++ " " ++ show (mx,my) @@ -822,7 +828,7 @@ updateNodeRef b force r = do else return b b'' <- if force then return b'{getSelectedNode=noRef} else return b' renderBorders r b'' - where getCurrFocused = maybe 0 index <$> (withoutFloating <$> getFloating <*> getStackSet) + where getCurrFocused = maybe 0 index <$> (withoutFloating <$> getFloating <*> getHidden <*> getStackSet) -- create border around focused node if necessary renderBorders :: Rectangle -> BinarySpacePartition a -> X (BinarySpacePartition a)