aboutsummaryrefslogtreecommitdiff
path: root/src/Internal/Windows.hs
blob: 98baa5178405b3be9077f9943b681f59b2cc8dc4 (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
module Internal.Windows where

import XMonad (windowset, X, Window, get)

import Control.Applicative ((<|>))
import XMonad.StackSet (Stack(..), StackSet(..), Screen(..), Workspace(..), integrate, integrate', allWindows)
import Data.Maybe (listToMaybe, catMaybes)
import qualified Data.Map as Map

mapWindows :: (Ord a, Ord b) => (a -> b) -> StackSet i l a s sd -> StackSet i l b s sd
mapWindows fn (StackSet cur vis hid float) =
  StackSet
    (mapWindowsScreen cur)
    (map mapWindowsScreen vis)
    (map mapWindowsWorkspace hid)
    (Map.mapKeys fn float)
  where
    mapWindowsScreen (Screen work a b) = Screen (mapWindowsWorkspace work) a b
    mapWindowsWorkspace (Workspace t l stack) =
      Workspace t l (fmap (mapStack fn) stack)

-- | What genius decided to hide the instances for the Stack type!!???
mapStack :: (a -> b) -> Stack a -> Stack b
mapStack fn (Stack focus up down) = Stack (fn focus) (map fn up) (map fn down)

getMaster :: StackSet i l a s sd -> Maybe a
getMaster (StackSet (Screen (Workspace _ _ ss) _ _) _ _ _) =
  head . integrate <$> ss

swapWindows :: (Ord a) => a -> a -> StackSet i l a s d -> StackSet i l a s d
swapWindows wa wb = mapWindows $ \w ->
  case w of
    _ | w == wa -> wb
    _ | w == wb -> wa
    _ -> w

data WindowLocation i l a s sd =
  OnScreen (Screen i l a s sd) |
  OnHiddenWorkspace (Workspace i l a) |
  Floating

getLocationWorkspace :: WindowLocation i l a s sd -> Maybe (Workspace i l a)
getLocationWorkspace (OnScreen (Screen w _ _)) = Just w
getLocationWorkspace (OnHiddenWorkspace w) = Just w
getLocationWorkspace _ = Nothing

workspaceMember :: (Eq a) => Workspace i l a -> a -> Bool
workspaceMember (Workspace _ _ s) w = w `elem` integrate' s

forAllWindows :: (Window -> X ()) -> X ()
forAllWindows fn = do
  stackSet <- windowset <$> get
  mapM_ fn (allWindows stackSet)

{- Finds a Window and returns the screen its on and the workspace its on.
 - Returns nothing if the window doesn't exist.
 -
 - If the window is not a screen Just (Nothing, workspace) is returned.
 - If the window is a floating window Just (Nothing, Nothing) is returned. -}
findWindow ::
    (Eq a) => StackSet i l a s sd -> a -> Maybe (WindowLocation i l a s sd)
findWindow (StackSet cur vis hid float) win =
    listToMaybe . catMaybes $
      map findWindowScreen (cur : vis) ++
        map findWindowWorkspace hid ++
          [findWindowFloat]

  where
    findWindowScreen s@(Screen ws _ _) =
      if workspaceMember ws win
        then Just (OnScreen s)
        else Nothing

    findWindowWorkspace w =
      if workspaceMember w win
        then Just (OnHiddenWorkspace w)
        else Nothing

    findWindowFloat =
      if win `elem` Map.keys float
        then Just Floating
        else Nothing