From 3cc28186cd3ab934e29c4864f7c6b074475906a1 Mon Sep 17 00:00:00 2001 From: Josh Rahm Date: Thu, 14 Apr 2022 01:24:30 -0600 Subject: Make workspaces more consistent --- src/Rahm/Desktop/Keys.hs | 44 +++++++++++++++++++++++++++--------------- src/Rahm/Desktop/Workspaces.hs | 28 ++++++++++++++++++++------- 2 files changed, 49 insertions(+), 23 deletions(-) (limited to 'src/Rahm') diff --git a/src/Rahm/Desktop/Keys.hs b/src/Rahm/Desktop/Keys.hs index 2f30763..6e16c25 100644 --- a/src/Rahm/Desktop/Keys.hs +++ b/src/Rahm/Desktop/Keys.hs @@ -5,6 +5,7 @@ import Data.Monoid (Endo(..)) import Control.Monad.Trans.Class import Control.Monad.Reader import Control.Monad.Writer +import Control.Monad.Trans.Maybe import Control.Monad.Loops (iterateWhile) import Control.Monad.Fix (fix) import Graphics.X11.ExtraTypes.XF86; @@ -267,30 +268,38 @@ keymap = runKeys $ do bind xK_g $ do let selectWorkspace :: (KeySym, String) -> Maybe (X WorkspaceId) selectWorkspace s = case s of - (_, [ch]) | isAlphaNum ch -> Just $ return [ch] + (_, [ch]) | isAlphaNum ch || ch == '*' -> Just $ return [ch] (_, "]") -> Just $ adjacentWorkspace next =<< getCurrentWorkspace (_, "[") -> Just $ adjacentWorkspace prev =<< getCurrentWorkspace (_, "}") -> Just $ adjacentScreen next (_, "{") -> Just $ adjacentScreen prev - (_, "/") -> Just $ runMaybeT $ do - windowId <- askWindowId - workspaceWithWindow askWindowId + (_, "^") -> Just firstWorkspaceId + (_, "$") -> Just lastWorkspaceId + (_, "/") -> Just $ do + cur <- getCurrentWorkspace + fromMaybe cur <$> runMaybeT (do + windowId <- MaybeT askWindowId + MaybeT $ workspaceWithWindow windowId) (_, " ") -> Just $ accompaningWorkspace <$> getCurrentWorkspace _ -> Nothing justMod $ - doc "Goto a workspace\n\n\t\ - - \If the second character typed is alpha-numeric, jump to that\n\t\ - \workspace. The workspace is created on-the-fly if such a workspace\n\t\ - \does not exist.\n\n\t\ - - \If the second character typed is:\n\t\t\ - \]: go to the next workspace\n\t\t\ - \[: go to the previous workspace\n\t\t\ - \}: cycle the workspaces on the screens to the right\n\t\t\ - \{: cycle the workspaces on the screens to the left\n\t\t\ - \: Jump to the accompaning workspace.\n\t\t\ + doc "Goto/Send/Etc To a workspace\n\n\t\ + + \Workspaces are alphanumeric characters. So if the next key typed is an\n\t\ + \alphanumeric character, that's the workspace to operate on\n\n\ + + \The following special characters can also reference workspaces:\n\t\t\ + \]: The next non-visible workspace\n\t\t\ + \[: The previous non-visible workspace\n\t\t\ + \}: The workspace on the screen to the right\n\t\t\ + \{: The workspace on the screen to the left\n\t\t\ + \: The accompaningWorkspace (toggled case)\n\t\t\ + \/: Prompt to select a window, and reference that workspace\n\t\t\ + \^: The first populated workspace\n\t\t\ + \$: The last populated workspace\n\t\t\ + \*: The hidden workspace.\n\t\t\ + \_: Black hole. Sending a window here closes it.\n\t\t\ \F1: display this help.\n" $ mapNextStringWithKeysym $ \_ keysym str -> case ((keysym, str), selectWorkspace (keysym, str)) of @@ -308,6 +317,7 @@ keymap = runKeys $ do mapNextStringWithKeysym $ \_ keysym str -> case ((keysym, str), selectWorkspace (keysym, str)) of (_, Just w) -> shiftToWorkspace =<< w + ((_, "_"), _) -> CopyWindow.kill1 _ -> return () controlMod $ @@ -332,6 +342,8 @@ keymap = runKeys $ do mapNextStringWithKeysym $ \_ keysym str -> case ((keysym, str), selectWorkspace (keysym, str)) of (_, Just ws) -> swapWorkspace =<< ws + ((_, "_"), _) -> + mapM_ (\w -> focus w >> CopyWindow.kill1) =<< windowsInCurrentWorkspace _ -> return () bind xK_h $ do diff --git a/src/Rahm/Desktop/Workspaces.hs b/src/Rahm/Desktop/Workspaces.hs index 87d112e..2a266b7 100644 --- a/src/Rahm/Desktop/Workspaces.hs +++ b/src/Rahm/Desktop/Workspaces.hs @@ -28,12 +28,13 @@ data WorkspaceState = Current | Hidden | Visible -- -- This function will sort the result by the workspace tag. getPopulatedWorkspaces :: - (Ord i) => W.StackSet i l a sid sd -> [(WorkspaceState, W.Workspace i l a)] + W.StackSet String l a sid sd -> [(WorkspaceState, W.Workspace String l a)] getPopulatedWorkspaces (W.StackSet (W.Screen cur _ _) vis hi _) = - sortOn (W.tag . snd) $ - mapMaybe (\w@(W.Workspace _ _ s) -> fmap (const (Hidden, w)) s) hi ++ - map (\(W.Screen w _ _) -> (Visible, w)) vis ++ - [(Current, cur)] + filter ((/="*") . W.tag . snd) $ + sortOn (W.tag . snd) $ + mapMaybe (\w@(W.Workspace _ _ s) -> fmap (const (Hidden, w)) s) hi ++ + map (\(W.Screen w _ _) -> (Visible, w)) vis ++ + [(Current, cur)] next :: Selector next = Selector $ \f l -> select f l l @@ -46,11 +47,24 @@ prev :: Selector prev = Selector $ \f l -> let (Selector fn) = next in fn f (reverse l) +lastWorkspaceId :: X WorkspaceId +lastWorkspaceId = + W.tag . snd . last <$> withWindowSet (return . getPopulatedWorkspaces) + +firstWorkspaceId :: X WorkspaceId +firstWorkspaceId = + W.tag . snd . head <$> withWindowSet (return . getPopulatedWorkspaces) + getCurrentWorkspace :: X WorkspaceId getCurrentWorkspace = withWindowSet $ \(W.StackSet (W.Screen (W.Workspace t _ _) _ _) _ _ _) -> do return t +windowsInCurrentWorkspace :: X [Window] +windowsInCurrentWorkspace = withWindowSet $ + \(W.StackSet (W.Screen (W.Workspace _ _ s) _ _) _ _ _) -> do + return $ W.integrate' s + getHorizontallyOrderedScreens :: W.StackSet wid l a ScreenId ScreenDetail -> [(Bool, W.Screen wid l a ScreenId ScreenDetail)] @@ -103,7 +117,7 @@ adjacentWorkspace :: Selector -> WorkspaceId -> X WorkspaceId adjacentWorkspace (Selector selector) from = withWindowSet $ \ss -> let tags = sort $ - W.tag . snd <$> (filter (\x -> fst x /= Visible) $ + W.tag . snd <$> filter (\x -> fst x /= Visible) ( getPopulatedWorkspaces ss) in return $ fromMaybe from $ selector (==from) tags @@ -117,7 +131,7 @@ adjacentScreen (Selector f) = do (screens, current) <- withWindowSet $ return . (getHorizontallyOrderedScreens &&& W.current) - return $ W.tag $ W.workspace $ fromMaybe current (snd <$> f fst screens) + return $ W.tag $ W.workspace $ maybe current snd (f fst screens) withScreen :: (WorkspaceId -> WindowSet -> WindowSet) -> Int -> X () withScreen fn n = do -- cgit