From 90949577aeb040012a49c7687bcfec8fcfb80e34 Mon Sep 17 00:00:00 2001 From: Spencer Janssen Date: Sat, 17 Jan 2009 05:04:32 +0100 Subject: Add XMonad.Actions.SpawnOn Ignore-this: 63869d1ab11f2ed5aab1690763065800 darcs-hash:20090117040432-25a6b-306aa18fed69a47197ca8c349cf6452939db5188.gz --- XMonad/Actions/SpawnOn.hs | 77 +++++++++++++++++++++++++++++++++++++++++++ XMonad/Hooks/ManageHelpers.hs | 12 +++++++ XMonad/Prompt/Shell.hs | 5 +-- 3 files changed, 92 insertions(+), 2 deletions(-) create mode 100644 XMonad/Actions/SpawnOn.hs (limited to 'XMonad') diff --git a/XMonad/Actions/SpawnOn.hs b/XMonad/Actions/SpawnOn.hs new file mode 100644 index 0000000..d452cdf --- /dev/null +++ b/XMonad/Actions/SpawnOn.hs @@ -0,0 +1,77 @@ +----------------------------------------------------------------------------- +-- | +-- Module : XMonad.Actions.SpawnOn +-- Copyright : (c) Spencer Janssen +-- License : BSD +-- +-- Maintainer : Spencer Janssen +-- Stability : unstable +-- Portability : unportable +-- +-- This module provides helper functions to be used in @manageHook@. Here's +-- how you might use this: +-- +-- > import XMonad.Hooks.ManageHelpers +-- > main = do +-- > sp <- mkSpawner +-- > xmonad defaultConfig { +-- > ... +-- > manageHook = spawnHook sp <+> manageHook defaultConfig +-- > ... +-- > } + +module XMonad.Actions.SpawnOn ( + Spawner, + mkSpawner, + manageSpawn, + spawnHere, + spawnOn, + shellPromptHere, + shellPromptOn +) where + +import Data.IORef +import System.Posix.Types (ProcessID) + +import XMonad +import qualified XMonad.StackSet as W + +import XMonad.Hooks.ManageHelpers +import XMonad.Prompt +import XMonad.Prompt.Shell + +newtype Spawner = Spawner {pidsRef :: IORef [(ProcessID, WorkspaceId)]} + +maxPids :: Int +maxPids = 5 + +mkSpawner :: (Functor m, MonadIO m) => m Spawner +mkSpawner = io . fmap Spawner $ newIORef [] + +manageSpawn :: Spawner -> ManageHook +manageSpawn sp = do + pids <- io . readIORef $ pidsRef sp + mp <- pid + case flip lookup pids =<< mp of + Just w -> doF (W.shift w) + Nothing -> doF id + +mkPrompt :: (String -> X ()) -> XPConfig -> X () +mkPrompt cb c = do + cmds <- io $ getCommands + mkXPrompt Shell c (getShellCompl cmds) cb + +shellPromptHere :: Spawner -> XPConfig -> X () +shellPromptHere sp = mkPrompt (spawnHere sp) + +shellPromptOn :: Spawner -> WorkspaceId -> XPConfig -> X () +shellPromptOn sp ws = mkPrompt (spawnOn sp ws) + +spawnHere :: Spawner -> String -> X () +spawnHere sp cmd = withWindowSet $ \ws -> spawnOn sp (currTag ws) cmd + where currTag = W.tag . W.workspace . W.current + +spawnOn :: Spawner -> WorkspaceId -> String -> X () +spawnOn sp ws cmd = do + p <- spawnPID cmd + io $ modifyIORef (pidsRef sp) (take maxPids . ((p, ws) :)) diff --git a/XMonad/Hooks/ManageHelpers.hs b/XMonad/Hooks/ManageHelpers.hs index 5dd8e32..e5f25e4 100644 --- a/XMonad/Hooks/ManageHelpers.hs +++ b/XMonad/Hooks/ManageHelpers.hs @@ -31,6 +31,7 @@ module XMonad.Hooks.ManageHelpers ( isKDETrayWindow, isFullscreen, isDialog, + pid, transientTo, maybeToDefinite, MaybeManageHook, @@ -49,6 +50,8 @@ import qualified XMonad.StackSet as W import Data.Maybe import Data.Monoid +import System.Posix (ProcessID) + -- | Denotes a side of a screen. @S@ stands for South, @NE@ for Northwest -- etc. @C@ stands for Center. data Side = SC | NC | CE | CW | SE | SW | NE | NW | C @@ -144,6 +147,15 @@ isDialog = ask >>= \w -> liftX $ do Just xs -> fromIntegral w_dialog `elem` xs _ -> False +pid :: Query (Maybe ProcessID) +pid = ask >>= \w -> liftX $ do + dpy <- asks display + a <- getAtom "_NET_WM_PID" + p <- io $ getWindowProperty32 dpy a w + return $ case p of + Just [x] -> Just (fromIntegral x) + _ -> Nothing + -- | A predicate to check whether a window is Transient. -- It holds the result which might be the window it is transient to -- or it might be 'Nothing'. diff --git a/XMonad/Prompt/Shell.hs b/XMonad/Prompt/Shell.hs index c659787..d1ea150 100644 --- a/XMonad/Prompt/Shell.hs +++ b/XMonad/Prompt/Shell.hs @@ -15,7 +15,8 @@ module XMonad.Prompt.Shell ( -- * Usage -- $usage - shellPrompt + Shell (..) + , shellPrompt , getCommands , getBrowser , getEditor @@ -141,4 +142,4 @@ getBrowser = env "BROWSER" "firefox" -- | Like 'getBrowser', but should be of a text editor. This gets the $EDITOR variable, defaulting to \"emacs\". getEditor :: IO String -getEditor = env "EDITOR" "emacs" \ No newline at end of file +getEditor = env "EDITOR" "emacs" -- cgit v1.2.3