aboutsummaryrefslogtreecommitdiff
path: root/src/Internal/Marking.hs
blob: c1234ec8d84e24f9532b31f25216a4fb4a27ceaa (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
{-# LANGUAGE ScopedTypeVariables #-}
module Internal.Marking where

import Internal.Windows (mapWindows, findWindow, getLocationWorkspace)
import XMonad
import XMonad.StackSet hiding (focus)
import Data.IORef
import Data.Map (Map)

import System.FilePath
import System.IO
import Control.Exception
import System.Environment

import qualified XMonad.Util.ExtensibleState as XS

import qualified Data.Map as Map

{- Submodule that handles marking windows so they can be jumped back to. -}

type Mark = Char

data MarkState =
  MarkState {
    markStateMap :: Map Mark Window 
  , markLast :: Maybe Window
  } deriving (Read, Show)


instance ExtensionClass MarkState where
  initialValue = MarkState Map.empty Nothing

greedyFocus :: Window -> X ()
greedyFocus win = do
    ws <- withWindowSet $ \ss ->
            return $ getLocationWorkspace =<< findWindow ss win
    mapM_ (windows . greedyView . tag) ws
    focus win

markCurrentWindow :: Mark -> X ()
markCurrentWindow mark = do
  withFocused $ \win ->
    XS.modify $ \state@(MarkState {markStateMap = ms}) ->
        state {
          markStateMap = Map.insert mark win ms
        }

saveLastMark :: X ()
saveLastMark =
  withFocused $ \win ->
      XS.modify $ \state -> state { markLast = Just win }

jumpToLast :: X ()
jumpToLast = do
  m <- markLast <$> XS.get
  saveLastMark
  mapM_ greedyFocus m

jumpToMark :: Mark -> X ()
jumpToMark mark = do
  MarkState {markStateMap = m} <- XS.get
  case Map.lookup mark m of
    Nothing -> return ()
    Just w -> do
      saveLastMark
      greedyFocus w

setFocusedWindow :: a -> StackSet i l a s sd -> StackSet i l a s sd
setFocusedWindow
  window
  (StackSet (Screen (Workspace t l stack) a b) vis hid float) =
    let newStack =
          case stack of
            Nothing -> Nothing
            Just (Stack _ up down) -> Just (Stack window up down) in
    (StackSet (Screen (Workspace t l newStack) a b) vis hid float)

swapWithFocused :: (Ord a) => a -> StackSet i l a s sd -> StackSet i l a s sd
swapWithFocused winToSwap stackSet =
  case peek stackSet of
    Nothing -> stackSet
    Just focused -> do
       setFocusedWindow winToSwap $
          mapWindows (
            \w -> if w == winToSwap then focused else w) stackSet

swapWithLastMark :: X ()
swapWithLastMark = do
  m <- markLast <$> XS.get
  saveLastMark

  case m of
    Nothing -> return ()
    Just win -> windows $ swapWithFocused win

swapWithMark :: Mark -> X ()
swapWithMark mark = do
  MarkState {markStateMap = m} <- XS.get
  saveLastMark

  case Map.lookup mark m of
    Nothing -> return ()
    Just winToSwap ->
      windows $ swapWithFocused winToSwap