mirror of
https://github.com/xmonad/xmonad.git
synced 2025-08-08 08:01:52 -07:00
add swapLeft and swapRight
This commit is contained in:
@@ -160,6 +160,9 @@ keys = M.fromList $
|
|||||||
, ((modMask, xK_j ), focusRight)
|
, ((modMask, xK_j ), focusRight)
|
||||||
, ((modMask, xK_k ), focusLeft)
|
, ((modMask, xK_k ), focusLeft)
|
||||||
|
|
||||||
|
, ((modMask, xK_Left ), swapLeft)
|
||||||
|
, ((modMask, xK_Right ), swapRight)
|
||||||
|
|
||||||
, ((modMask, xK_h ), sendMessage Shrink)
|
, ((modMask, xK_h ), sendMessage Shrink)
|
||||||
, ((modMask, xK_l ), sendMessage Expand)
|
, ((modMask, xK_l ), sendMessage Expand)
|
||||||
|
|
||||||
@@ -172,7 +175,7 @@ keys = M.fromList $
|
|||||||
, ((modMask .|. shiftMask .|. controlMask, xK_q ), restart Nothing False)
|
, ((modMask .|. shiftMask .|. controlMask, xK_q ), restart Nothing False)
|
||||||
|
|
||||||
-- Cycle the current tiling order
|
-- Cycle the current tiling order
|
||||||
, ((modMask, xK_Return), swap)
|
, ((modMask, xK_Return), swapMaster)
|
||||||
|
|
||||||
] ++
|
] ++
|
||||||
-- Keybindings to get to each workspace:
|
-- Keybindings to get to each workspace:
|
||||||
|
@@ -51,13 +51,15 @@ unmanage :: Window -> X ()
|
|||||||
unmanage = windows . W.delete
|
unmanage = windows . W.delete
|
||||||
|
|
||||||
-- | focus. focus window to the left or right.
|
-- | focus. focus window to the left or right.
|
||||||
focusLeft, focusRight :: X ()
|
focusLeft, focusRight, swapLeft, swapRight :: X ()
|
||||||
focusLeft = windows W.focusLeft
|
focusLeft = windows W.focusLeft
|
||||||
focusRight = windows W.focusRight
|
focusRight = windows W.focusRight
|
||||||
|
swapLeft = windows W.swapLeft
|
||||||
|
swapRight = windows W.swapRight
|
||||||
|
|
||||||
-- | swap. Move the currently focused window into the master frame
|
-- | swapMaster. Move the currently focused window into the master frame
|
||||||
swap :: X ()
|
swapMaster :: X ()
|
||||||
swap = windows W.swap
|
swapMaster = windows W.swapMaster
|
||||||
|
|
||||||
-- | shift. Move a window to a new workspace, 0 indexed.
|
-- | shift. Move a window to a new workspace, 0 indexed.
|
||||||
shift :: WorkspaceId -> X ()
|
shift :: WorkspaceId -> X ()
|
||||||
|
31
StackSet.hs
31
StackSet.hs
@@ -77,8 +77,8 @@
|
|||||||
module StackSet (
|
module StackSet (
|
||||||
StackSet(..), Workspace(..), Screen(..), Stack(..),
|
StackSet(..), Workspace(..), Screen(..), Stack(..),
|
||||||
new, view, lookupWorkspace, peek, index, focusLeft, focusRight,
|
new, view, lookupWorkspace, peek, index, focusLeft, focusRight,
|
||||||
focusWindow, member, findIndex, insertLeft, delete, swap, shift,
|
focusWindow, member, findIndex, insertLeft, delete, shift,
|
||||||
modify -- needed by users
|
swapMaster, swapLeft, swapRight, modify -- needed by users
|
||||||
) where
|
) where
|
||||||
|
|
||||||
import Data.Maybe (listToMaybe)
|
import Data.Maybe (listToMaybe)
|
||||||
@@ -92,10 +92,11 @@ import qualified Data.List as L (delete,find,genericSplitAt)
|
|||||||
-- index,
|
-- index,
|
||||||
-- peek, -- was: peek/peekStack
|
-- peek, -- was: peek/peekStack
|
||||||
-- focusLeft, focusRight, -- was: rotate
|
-- focusLeft, focusRight, -- was: rotate
|
||||||
|
-- swapLeft, swapRight
|
||||||
-- focus -- was: raiseFocus
|
-- focus -- was: raiseFocus
|
||||||
-- insertLeft, -- was: insert/push
|
-- insertLeft, -- was: insert/push
|
||||||
-- delete,
|
-- delete,
|
||||||
-- swap, -- was: promote
|
-- swapMaster, -- was: promote/swap
|
||||||
-- member,
|
-- member,
|
||||||
-- shift,
|
-- shift,
|
||||||
-- lookupWorkspace, -- was: workspace
|
-- lookupWorkspace, -- was: workspace
|
||||||
@@ -239,12 +240,18 @@ index = with [] $ \(Node t l r) -> reverse l ++ t : r
|
|||||||
-- let is = t : r ++ reverse l in take (length is) (dropWhile (/= m) (cycle is))
|
-- let is = t : r ++ reverse l in take (length is) (dropWhile (/= m) (cycle is))
|
||||||
|
|
||||||
--
|
--
|
||||||
-- /O(1), O(w) on the wrapping case/. Move the window focus left or
|
-- /O(1), O(w) on the wrapping case/.
|
||||||
|
--
|
||||||
|
-- focusLeft, focusRight. Move the window focus left or
|
||||||
-- right, wrapping if we reach the end. The wrapping should model a
|
-- right, wrapping if we reach the end. The wrapping should model a
|
||||||
-- 'cycle' on the current stack. The 'master' window, and window order,
|
-- 'cycle' on the current stack. The 'master' window, and window order,
|
||||||
-- are unaffected by movement of focus.
|
-- are unaffected by movement of focus.
|
||||||
--
|
--
|
||||||
focusLeft, focusRight :: StackSet i a s -> StackSet i a s
|
-- swapLeft, swapRight. Swap the focused window with its left or right
|
||||||
|
-- neighbour in the stack ordering, wrapping if we reach the end. Again
|
||||||
|
-- the wrapping model should 'cycle' on the current stack.
|
||||||
|
--
|
||||||
|
focusLeft, focusRight, swapLeft, swapRight :: StackSet i a s -> StackSet i a s
|
||||||
focusLeft = modify Empty $ \c -> case c of
|
focusLeft = modify Empty $ \c -> case c of
|
||||||
Node _ [] [] -> c
|
Node _ [] [] -> c
|
||||||
Node t (l:ls) rs -> Node l ls (t:rs)
|
Node t (l:ls) rs -> Node l ls (t:rs)
|
||||||
@@ -255,6 +262,16 @@ focusRight = modify Empty $ \c -> case c of
|
|||||||
Node t ls (r:rs) -> Node r (t:ls) rs
|
Node t ls (r:rs) -> Node r (t:ls) rs
|
||||||
Node t ls [] -> Node x [] (xs ++ [t]) where (x:xs) = reverse ls
|
Node t ls [] -> Node x [] (xs ++ [t]) where (x:xs) = reverse ls
|
||||||
|
|
||||||
|
swapLeft = modify Empty $ \c -> case c of
|
||||||
|
Node _ [] [] -> c
|
||||||
|
Node t (l:ls) rs -> Node t ls (l:rs)
|
||||||
|
Node t [] rs -> Node t (reverse rs) []
|
||||||
|
|
||||||
|
swapRight = modify Empty $ \c -> case c of
|
||||||
|
Node _ [] [] -> c
|
||||||
|
Node t ls (r:rs) -> Node t (r:ls) rs
|
||||||
|
Node t ls [] -> Node t [] (reverse ls)
|
||||||
|
|
||||||
--
|
--
|
||||||
-- | /O(1) on current window, O(n) in general/. Focus the window 'w',
|
-- | /O(1) on current window, O(n) in general/. Focus the window 'w',
|
||||||
-- and set its workspace as current.
|
-- and set its workspace as current.
|
||||||
@@ -342,8 +359,8 @@ delete w s | Just w == peek s = remove s -- common case.
|
|||||||
-- /O(s)/. Set the master window to the focused window.
|
-- /O(s)/. Set the master window to the focused window.
|
||||||
-- The old master window is swapped in the tiling order with the focused window.
|
-- The old master window is swapped in the tiling order with the focused window.
|
||||||
-- Focus stays with the item moved.
|
-- Focus stays with the item moved.
|
||||||
swap :: StackSet i a s -> StackSet i a s
|
swapMaster :: StackSet i a s -> StackSet i a s
|
||||||
swap = modify Empty $ \c -> case c of
|
swapMaster = modify Empty $ \c -> case c of
|
||||||
Node _ [] _ -> c -- already master.
|
Node _ [] _ -> c -- already master.
|
||||||
Node t ls rs -> Node t [] (ys ++ x : rs) where (x:ys) = reverse ls
|
Node t ls rs -> Node t [] (ys ++ x : rs) where (x:ys) = reverse ls
|
||||||
|
|
||||||
|
@@ -155,7 +155,12 @@ prop_delete_I (x :: T) = invariant $
|
|||||||
Nothing -> x
|
Nothing -> x
|
||||||
Just i -> delete i x
|
Just i -> delete i x
|
||||||
|
|
||||||
prop_swap_I (x :: T) = invariant $ swap x
|
prop_swap_master_I (x :: T) = invariant $ swapMaster x
|
||||||
|
|
||||||
|
prop_swap_left_I (n :: NonNegative Int) (x :: T) =
|
||||||
|
invariant $ foldr (const swapLeft ) x [1..n]
|
||||||
|
prop_swap_right_I (n :: NonNegative Int) (x :: T) =
|
||||||
|
invariant $ foldr (const swapRight) x [1..n]
|
||||||
|
|
||||||
prop_shift_I (n :: NonNegative Int) (x :: T) =
|
prop_shift_I (n :: NonNegative Int) (x :: T) =
|
||||||
fromIntegral n < size x ==> invariant $ shift (fromIntegral n) x
|
fromIntegral n < size x ==> invariant $ shift (fromIntegral n) x
|
||||||
@@ -349,8 +354,8 @@ prop_insert_peek (n :: Positive Int) (m :: Positive Int) (NonEmptyNubList is) =
|
|||||||
--
|
--
|
||||||
prop_insert_delete n x = not (member n x) ==> delete n (insertLeft n y) == (y :: T)
|
prop_insert_delete n x = not (member n x) ==> delete n (insertLeft n y) == (y :: T)
|
||||||
where
|
where
|
||||||
y = swap x -- sets the master window to the current focus.
|
y = swapMaster x -- sets the master window to the current focus.
|
||||||
-- otherwise, we don't have a rule for where master goes.
|
-- otherwise, we don't have a rule for where master goes.
|
||||||
|
|
||||||
-- inserting n elements increases current stack size by n
|
-- inserting n elements increases current stack size by n
|
||||||
prop_size_insert is (n :: Positive Int) (m :: Positive Int) =
|
prop_size_insert is (n :: Positive Int) (m :: Positive Int) =
|
||||||
@@ -379,7 +384,7 @@ prop_delete_insert (x :: T) =
|
|||||||
Nothing -> True
|
Nothing -> True
|
||||||
Just n -> insertLeft n (delete n y) == y
|
Just n -> insertLeft n (delete n y) == y
|
||||||
where
|
where
|
||||||
y = swap x
|
y = swapMaster x
|
||||||
|
|
||||||
-- delete should be local
|
-- delete should be local
|
||||||
prop_delete_local (x :: T) =
|
prop_delete_local (x :: T) =
|
||||||
@@ -388,20 +393,11 @@ prop_delete_local (x :: T) =
|
|||||||
Just i -> hidden_spaces x == hidden_spaces (delete i x)
|
Just i -> hidden_spaces x == hidden_spaces (delete i x)
|
||||||
|
|
||||||
-- ---------------------------------------------------------------------
|
-- ---------------------------------------------------------------------
|
||||||
-- swap: setting the master window
|
-- swapLeft, swapRight, swapMaster: reordiring windows
|
||||||
|
|
||||||
-- prop_swap_reversible a b xs = swap a b (swap a b ys) == ys
|
|
||||||
-- where ys = nub xs :: [Int]
|
|
||||||
|
|
||||||
-- swap doesn't change focus
|
|
||||||
prop_swap_focus (x :: T)
|
|
||||||
= case peek x of
|
|
||||||
Nothing -> True
|
|
||||||
Just f -> focus (stack (workspace $ current (swap x))) == f
|
|
||||||
|
|
||||||
-- swap is local
|
|
||||||
prop_swap_local (x :: T) = hidden_spaces x == hidden_spaces (swap x)
|
|
||||||
|
|
||||||
|
-- swap is trivially reversible
|
||||||
|
prop_swap_left (x :: T) = (swapLeft (swapRight x)) == x
|
||||||
|
prop_swap_right (x :: T) = (swapRight (swapLeft x)) == x
|
||||||
-- TODO swap is reversible
|
-- TODO swap is reversible
|
||||||
-- swap is reversible, but involves moving focus back the window with
|
-- swap is reversible, but involves moving focus back the window with
|
||||||
-- master on it. easy to do with a mouse...
|
-- master on it. easy to do with a mouse...
|
||||||
@@ -414,7 +410,26 @@ prop_promote_reversible x b = (not . null . fromMaybe [] . flip index x . curren
|
|||||||
(Just (z:_)) = flip index x . current $ x
|
(Just (z:_)) = flip index x . current $ x
|
||||||
-}
|
-}
|
||||||
|
|
||||||
prop_swap_idempotent (x :: T) = swap (swap x) == swap x
|
-- swap doesn't change focus
|
||||||
|
prop_swap_master_focus (x :: T) = peek x == (peek $ swapMaster x)
|
||||||
|
-- = case peek x of
|
||||||
|
-- Nothing -> True
|
||||||
|
-- Just f -> focus (stack (workspace $ current (swap x))) == f
|
||||||
|
prop_swap_left_focus (x :: T) = peek x == (peek $ swapLeft x)
|
||||||
|
prop_swap_right_focus (x :: T) = peek x == (peek $ swapRight x)
|
||||||
|
|
||||||
|
-- swap is local
|
||||||
|
prop_swap_master_local (x :: T) = hidden_spaces x == hidden_spaces (swapMaster x)
|
||||||
|
prop_swap_left_local (x :: T) = hidden_spaces x == hidden_spaces (swapLeft x)
|
||||||
|
prop_swap_right_local (x :: T) = hidden_spaces x == hidden_spaces (swapRight x)
|
||||||
|
|
||||||
|
-- rotation through the height of a stack gets us back to the start
|
||||||
|
prop_swap_all_l (x :: T) = (foldr (const swapLeft) x [1..n]) == x
|
||||||
|
where n = length (index x)
|
||||||
|
prop_swap_all_r (x :: T) = (foldr (const swapRight) x [1..n]) == x
|
||||||
|
where n = length (index x)
|
||||||
|
|
||||||
|
prop_swap_master_idempotent (x :: T) = swapMaster (swapMaster x) == swapMaster x
|
||||||
|
|
||||||
-- ---------------------------------------------------------------------
|
-- ---------------------------------------------------------------------
|
||||||
-- shift
|
-- shift
|
||||||
@@ -429,7 +444,7 @@ prop_shift_reversible (r :: Int) (x :: T) =
|
|||||||
Nothing -> True
|
Nothing -> True
|
||||||
Just _ -> normal ((view n . shift n . view i . shift i) y) == normal y
|
Just _ -> normal ((view n . shift n . view i . shift i) y) == normal y
|
||||||
where
|
where
|
||||||
y = swap x
|
y = swapMaster x
|
||||||
|
|
||||||
------------------------------------------------------------------------
|
------------------------------------------------------------------------
|
||||||
-- some properties for layouts:
|
-- some properties for layouts:
|
||||||
@@ -523,10 +538,18 @@ main = do
|
|||||||
,("delete is reversible", mytest prop_delete_insert)
|
,("delete is reversible", mytest prop_delete_insert)
|
||||||
,("delete is local" , mytest prop_delete_local)
|
,("delete is local" , mytest prop_delete_local)
|
||||||
|
|
||||||
,("swap: invariant " , mytest prop_swap_I)
|
,("swapMaster: invariant", mytest prop_swap_master_I)
|
||||||
,("swap id on focus" , mytest prop_swap_focus)
|
,("swapLeft: invariant" , mytest prop_swap_left_I)
|
||||||
,("swap is idempotent" , mytest prop_swap_idempotent)
|
,("swapRight: invariant", mytest prop_swap_right_I)
|
||||||
,("swap is local" , mytest prop_swap_local)
|
,("swapMaster id on focus", mytest prop_swap_master_focus)
|
||||||
|
,("swapLeft id on focus", mytest prop_swap_left_focus)
|
||||||
|
,("swapRight id on focus", mytest prop_swap_right_focus)
|
||||||
|
,("swapMaster is idempotent", mytest prop_swap_master_idempotent)
|
||||||
|
,("swap all left " , mytest prop_swap_all_l)
|
||||||
|
,("swap all right " , mytest prop_swap_all_r)
|
||||||
|
,("swapMaster is local" , mytest prop_swap_master_local)
|
||||||
|
,("swapLeft is local" , mytest prop_swap_left_local)
|
||||||
|
,("swapRight is local" , mytest prop_swap_right_local)
|
||||||
|
|
||||||
,("shift: invariant" , mytest prop_shift_I)
|
,("shift: invariant" , mytest prop_shift_I)
|
||||||
,("shift is reversible" , mytest prop_shift_reversible)
|
,("shift is reversible" , mytest prop_shift_reversible)
|
||||||
|
Reference in New Issue
Block a user