aboutsummaryrefslogtreecommitdiffstats
path: root/XMonad/Actions/GridSelect.hs
diff options
context:
space:
mode:
Diffstat (limited to 'XMonad/Actions/GridSelect.hs')
-rw-r--r--XMonad/Actions/GridSelect.hs84
1 files changed, 54 insertions, 30 deletions
diff --git a/XMonad/Actions/GridSelect.hs b/XMonad/Actions/GridSelect.hs
index ffde014..02d0ee0 100644
--- a/XMonad/Actions/GridSelect.hs
+++ b/XMonad/Actions/GridSelect.hs
@@ -1,4 +1,4 @@
-{-# LANGUAGE ScopedTypeVariables #-}
+{-# LANGUAGE ScopedTypeVariables, GeneralizedNewtypeDeriving #-}
-----------------------------------------------------------------------------
-- |
-- Module : XMonad.Actions.GridSelect
@@ -32,11 +32,14 @@ module XMonad.Actions.GridSelect (
colorRangeFromClassName
) where
import Data.Maybe
+import Data.Traversable (traverse)
import Data.Bits
+import Control.Applicative
import Control.Monad.State
import Control.Arrow
import Data.List as L
-import XMonad
+import qualified Data.Map as M
+import XMonad hiding (liftX)
import XMonad.Util.Font
import XMonad.Prompt (mkUnmanagedWindow)
import XMonad.StackSet as W
@@ -70,9 +73,12 @@ data GSConfig a = GSConfig {
gs_cellwidth :: Integer,
gs_cellpadding :: Integer,
gs_colorizer :: a -> Bool -> X (String, String),
- gs_font :: String
+ gs_font :: String,
+ gs_navigate :: NavigateMap
}
+type NavigateMap = M.Map (KeyMask,KeySym) (TwoDPosition -> TwoDPosition)
+
type TwoDPosition = (Integer, Integer)
type TwoDElementMap a = [(TwoDPosition,(String,a))]
@@ -86,7 +92,18 @@ data TwoDState a = TwoDState { td_curpos :: TwoDPosition
, td_drawingWin :: Window
}
-type TwoD a b = StateT (TwoDState a) X b
+newtype TwoD a b = TwoD { unTwoD :: StateT (TwoDState a) X b }
+ deriving (Monad,Functor,MonadState (TwoDState a))
+
+instance Applicative (TwoD a) where
+ (<*>) = ap
+ pure = return
+
+liftX :: X a1 -> TwoD a a1
+liftX = TwoD . lift
+
+evalTwoD :: TwoD a1 a -> TwoDState a1 -> X a
+evalTwoD m s = flip evalStateT s $ unTwoD m
diamondLayer :: (Enum b', Num b') => b' -> [(b', b')]
-- FIXME remove nub
@@ -148,8 +165,8 @@ updateElements elementmap = do
cellheight = gs_cellheight gsconfig
paneX' = div (paneX-cellwidth) 2
paneY' = div (paneY-cellheight) 2
- updateElement (pos@(x,y),(text, element)) = lift $ do
- colors <- (gs_colorizer gsconfig) element (pos == curpos)
+ updateElement (pos@(x,y),(text, element)) = liftX $ do
+ colors <- gs_colorizer gsconfig element (pos == curpos)
drawWinBox win font
colors
cellheight
@@ -158,12 +175,11 @@ updateElements elementmap = do
(paneX'+x*cellwidth)
(paneY'+y*cellheight)
(gs_cellpadding gsconfig)
- mapM updateElement elementmap
- return ()
+ mapM_ updateElement elementmap
eventLoop :: TwoD a (Maybe a)
eventLoop = do
- (keysym,string,event) <- lift $ withDisplay $ \d -> liftIO $ allocaXEvent $ \e -> do
+ (keysym,string,event) <- liftX $ withDisplay $ \d -> liftIO $ allocaXEvent $ \e -> do
nextEvent d e
ev <- getEvent e
(ks,s) <- if ev_event_type ev == keyPress
@@ -172,23 +188,19 @@ eventLoop = do
return (ks,s,ev)
handle (fromMaybe xK_VoidSymbol keysym,string) event
-handle :: (KeySym, String)
- -> Event
- -> StateT (TwoDState a) X (Maybe a)
-handle (ks,_) (KeyEvent {ev_event_type = t})
+handle :: (KeySym, t) -> Event -> TwoD a (Maybe a)
+handle (ks,_) (KeyEvent {ev_event_type = t, ev_state = m })
| t == keyPress && ks == xK_Escape = return Nothing
- | t == keyPress && (ks == xK_Left || ks == xK_h) = diffAndRefresh (-1,0)
- | t == keyPress && (ks == xK_Right || ks == xK_l) = diffAndRefresh (1,0)
- | t == keyPress && (ks == xK_Down || ks == xK_j) = diffAndRefresh (0,1)
- | t == keyPress && (ks == xK_Up || ks == xK_k) = diffAndRefresh (0,-1)
| t == keyPress && ks == xK_Return = do
(TwoDState { td_curpos = pos, td_elementmap = elmap }) <- get
return $ fmap (snd . snd) $ findInElementMap pos elmap
+ | t == keyPress = fmap join $ traverse diffAndRefresh . M.lookup (m,ks)
+ =<< gets (gs_navigate . td_gsconfig)
where diffAndRefresh diff = do
state <- get
let elmap = td_elementmap state
oldPos = td_curpos state
- newPos = oldPos `tupadd` diff
+ newPos = diff oldPos
newSelectedEl = findInElementMap newPos elmap
when (isJust newSelectedEl) $ do
put state { td_curpos = newPos }
@@ -197,8 +209,8 @@ handle (ks,_) (KeyEvent {ev_event_type = t})
handle _ (ButtonEvent { ev_event_type = t, ev_x = x, ev_y = y })
| t == buttonRelease = do
- (TwoDState { td_elementmap = elmap, td_paneX = px, td_paneY = py,
- td_gsconfig = (GSConfig ch cw _ _ _) }) <- get
+ TwoDState { td_elementmap = elmap, td_paneX = px, td_paneY = py,
+ td_gsconfig = (GSConfig ch cw _ _ _ _) } <- get
let gridX = (fi x - (px - cw) `div` 2) `div` cw
gridY = (fi y - (py - ch) `div` 2) `div` ch
case lookup (gridX,gridY) elmap of
@@ -306,15 +318,15 @@ gridselect gsconfig elmap =
restrictX = floor $ restriction screenWidth gs_cellwidth
restrictY = floor $ restriction screenHeight gs_cellheight
elmap' = zip (diamondRestrict restrictX restrictY) elmap
- selectedElement <- evalStateT (updateAllElements >> eventLoop)
- (TwoDState (0,0)
- elmap'
- gsconfig
- font
- screenWidth
- screenHeight
- win)
- return selectedElement
+
+ evalTwoD (updateAllElements >> eventLoop)
+ (TwoDState (0,0)
+ elmap'
+ gsconfig
+ font
+ screenWidth
+ screenHeight
+ win)
else
return Nothing
liftIO $ do
@@ -354,7 +366,19 @@ defaultGSConfig = buildDefaultGSConfig fromClassName
-- | Builds a default gs config from a colorizer function.
buildDefaultGSConfig :: (a -> Bool -> X (String,String)) -> GSConfig a
-buildDefaultGSConfig col = GSConfig 50 130 10 col "xft:Sans-8"
+buildDefaultGSConfig col = GSConfig 50 130 10 col "xft:Sans-8" defaultGSNav
+
+defaultGSNav :: NavigateMap
+defaultGSNav = M.map tupadd $ M.fromList
+ [((0,xK_Left) ,(-1,0))
+ ,((0,xK_h) ,(-1,0))
+ ,((0,xK_Right),(1,0))
+ ,((0,xK_l) ,(1,0))
+ ,((0,xK_Down) ,(0,1))
+ ,((0,xK_j) ,(0,1))
+ ,((0,xK_Up) ,(0,-1))
+ ,((0,xK_k) ,(0,-1))
+ ]
borderColor :: String
borderColor = "white"