From cd08ed8a005a38e54231f71dbe24e15d251bfbdd Mon Sep 17 00:00:00 2001 From: Matthias Schiffer Date: Fri, 25 Feb 2011 19:44:32 +0100 Subject: Allow spawning processes bound to workspaces --- lib/ProcessWorkspaces.hs | 89 ++++++++++++++++++++++++++++++++++++++++++++++++ lib/Storage.hs | 65 +++++++++++++++++++++++++++++++++++ 2 files changed, 154 insertions(+) create mode 100644 lib/ProcessWorkspaces.hs create mode 100644 lib/Storage.hs (limited to 'lib') diff --git a/lib/ProcessWorkspaces.hs b/lib/ProcessWorkspaces.hs new file mode 100644 index 0000000..69ab48d --- /dev/null +++ b/lib/ProcessWorkspaces.hs @@ -0,0 +1,89 @@ +{-# LANGUAGE DeriveDataTypeable, TypeSynonymInstances, MultiParamTypeClasses, PatternGuards #-} + +module ProcessWorkspaces ( setProcessWorkspace + , getProcessWorkspace + , moveWindowHook + , processWorkspaceStorage + , spawnOn + , spawnOnCurrent + ) where + +import XMonad hiding (moveWindow) +import qualified XMonad.StackSet as W + +import XMonad.Layout.LayoutModifier (LayoutModifier(..), ModifiedLayout(..)) +import XMonad.Hooks.ManageHelpers (pid) +import Graphics.X11.Types (Window) + +import System.Posix.Process (getProcessPriority) +import System.Posix.Types (ProcessID) + +import Prelude hiding ( catch ) +import Control.OldException (catch) +import Control.Monad +import Data.Maybe +import Data.Monoid +import qualified Data.Map as M + +import Storage + + +moveWindowHook :: ManageHook +moveWindowHook = do + mp <- pid + io $ appendFile "/tmp/test" $ "Pid: " ++ show mp ++ "\n" + case mp of + Just p -> do + mws <- liftX $ getProcessWorkspace p + io $ appendFile "/tmp/test" $ "WS: " ++ show mws ++ "\n" + case mws of + Just ws -> do + io $ appendFile "/tmp/test" $ show ws ++ "\n" + doShift ws + _ -> + idHook + _ -> + idHook + + +data ProcessWorkspaceStoreData = ProcessWorkspaceStoreData (M.Map ProcessID WorkspaceId) + deriving (Typeable, Show, Read) +instance StoreData ProcessWorkspaceStoreData + +processWorkspaceStorage :: (LayoutClass l a) => l a -> ModifiedLayout (Storage ProcessWorkspaceStoreData) l a +processWorkspaceStorage = storage $ ProcessWorkspaceStoreData M.empty + +setProcessWorkspace :: ProcessID -> WorkspaceId -> X () +setProcessWorkspace pid ws = do + io $ appendFile "/tmp/test" $ "Added " ++ show (pid, ws) ++ "\n" + ProcessWorkspaceStoreData map <- liftM (fromMaybe $ ProcessWorkspaceStoreData M.empty) $ getStoreData + map' <- filterPIDMap $ M.insert pid ws map + setStoreData $ ProcessWorkspaceStoreData map' + io (appendFile "/tmp/test" $ show map' ++ "\n") + +getProcessWorkspace :: ProcessID -> X (Maybe WorkspaceId) +getProcessWorkspace pid = getStoreData >>= return . join . fmap (\(ProcessWorkspaceStoreData map) -> M.lookup pid map) + + +spawnOn :: WorkspaceId -> String -> X () +spawnOn ws x = do + pid <- spawnPID x + setProcessWorkspace pid ws + +spawnOnCurrent :: String -> X () +spawnOnCurrent x = gets (W.currentTag . windowset) >>= \ws -> spawnOn ws x + + +catchX' :: X a -> X a -> X a +catchX' job errcase = do + st <- get + c <- ask + (a, s') <- io $ runX c st job `catch` \_ -> runX c st errcase + put s' + return a + +filterPIDMap :: M.Map ProcessID a -> X (M.Map ProcessID a) +filterPIDMap = liftM M.fromAscList . filterM (pidExists . fst) . M.toAscList + where + pidExists :: ProcessID -> X Bool + pidExists pid = catchX' (io (getProcessPriority pid) >> return True) (return False) diff --git a/lib/Storage.hs b/lib/Storage.hs new file mode 100644 index 0000000..6a8608b --- /dev/null +++ b/lib/Storage.hs @@ -0,0 +1,65 @@ +{-# LANGUAGE DeriveDataTypeable, ExistentialQuantification, TypeSynonymInstances, MultiParamTypeClasses, ScopedTypeVariables, FlexibleInstances, PatternGuards #-} + +module Storage ( StoreData + , Storage + , storage + , getStoreData + , setStoreData + , updateStoreData + ) where + +import XMonad +import qualified XMonad.StackSet as W +import XMonad.Layout.LayoutModifier (LayoutModifier(..), ModifiedLayout(..)) + +import Control.Applicative ((<$>)) +import Control.Monad + +import Data.IORef +import qualified Data.Map as M +import Data.Maybe +import Data.Typeable + + +class (Typeable d, Show d, Read d) => StoreData d + + +data (StoreData d) => StorageMessage d = GetStoreData (IORef (Maybe d)) | SetStoreData d + deriving Typeable +instance (StoreData d) => Message (StorageMessage d) + + +data (StoreData d) => Storage d a = Storage d deriving (Show, Read) + +instance (StoreData d) => LayoutModifier (Storage d) a where + modifierDescription _ = "Storage" + + handleMess (Storage d) m + | Just (GetStoreData ref :: StorageMessage d) <- fromMessage m = do + io $ writeIORef ref $ Just d + return $ Nothing + + | Just (SetStoreData d' :: StorageMessage d) <- fromMessage m = do + return $ Just $ Storage d' + + handleMess _ _ = return Nothing + + +storage :: (LayoutClass l a, StoreData d) => d -> l a -> ModifiedLayout (Storage d) l a +storage def = ModifiedLayout $ Storage def + + +getStoreData :: StoreData d => X (Maybe d) +getStoreData = do + ref <- io . newIORef $ Nothing + broadcastMessage $ GetStoreData ref + io . readIORef $ ref + + +setStoreData :: StoreData d => d -> X () +setStoreData = broadcastMessage . SetStoreData + +updateStoreData :: StoreData d => (d -> d) -> X () +updateStoreData f = do + d <- getStoreData + when (isJust d) $ setStoreData . f $ fromJust d \ No newline at end of file -- cgit v1.2.3