mirror of
https://github.com/xmonad/xmonad.git
synced 2025-08-01 04:31:53 -07:00
In order to give a better account of how focus and master interact, and how each operation affects focus, we reimplement the StackSet type as a two level nested 'Zipper'. To quote Oleg: A Zipper is essentially an `updateable' and yet pure functional cursor into a data structure. Zipper is also a delimited continuation reified as a data structure. That is, we use the Zipper as a cursor which encodes the window which is in focus. Thus our data structure tracks focus correctly by construction! We then get simple, obvious semantics for e.g. insert, in terms of how it affects focus/master. Our transient-messes-with-focus bug evaporates. 'swap' becomes trivial. By moving focus directly into the stackset, we can toss some QC properties about focus handling: it is simply impossible now for focus to go wrong. As a benefit, we get a dozen new QC properties for free, governing how master and focus operate. The encoding of focus in the data type also simplifies the focus handling in Operations: several operations affecting focus are now simply wrappers over StackSet. For the full story, please read the StackSet module, and the QC properties. Finally, we save ~40 lines with the simplified logic in Operations.hs For more info, see the blog post on the implementation, http://cgi.cse.unsw.edu.au/~dons/blog/2007/05/17#xmonad_part1b_zipper
190 lines
6.6 KiB
Haskell
190 lines
6.6 KiB
Haskell
-----------------------------------------------------------------------------
|
|
-- |
|
|
-- Module : Config.hs
|
|
-- Copyright : (c) Spencer Janssen 2007
|
|
-- License : BSD3-style (see LICENSE)
|
|
--
|
|
-- Maintainer : dons@cse.unsw.edu.au
|
|
-- Stability : stable
|
|
-- Portability : portable
|
|
--
|
|
------------------------------------------------------------------------
|
|
--
|
|
-- This module specifies configurable defaults for xmonad. If you change
|
|
-- values here, be sure to recompile and restart (mod-shift-ctrl-q) xmonad,
|
|
-- for the changes to take effect.
|
|
--
|
|
|
|
module Config where
|
|
|
|
--
|
|
-- xmonad bindings follow mostly the dwm/wmii conventions:
|
|
--
|
|
-- key combination action
|
|
--
|
|
-- mod-shift-return new xterm
|
|
-- mod-p launch dmenu
|
|
-- mod-shift-p launch gmrun
|
|
--
|
|
-- mod-space switch tiling mode
|
|
-- mod-n nudge current window into fullscreen mode
|
|
--
|
|
-- mod-tab shift focus to next window in stack
|
|
-- mod-j shift focus to next window in stack
|
|
-- mod-k shift focus previous window in stack
|
|
--
|
|
-- mod-h decrease the size of the master area
|
|
-- mod-l increase the size of the master area
|
|
--
|
|
-- mod-shift-c kill client
|
|
-- mod-shift-q exit window manager
|
|
-- mod-shift-ctrl-q restart window manager ('xmonad' must be in $PATH)
|
|
--
|
|
-- mod-return swap focused window with master window
|
|
--
|
|
-- mod-1..9 switch to workspace N
|
|
-- mod-shift-1..9 move client to workspace N
|
|
--
|
|
-- mod-w,e,r switch to physical/Xinerama screen 1, 2 or 3.
|
|
--
|
|
-- xmonad places each window into a "workspace." Each workspace can have
|
|
-- any number of windows, which you can cycle though with mod-j and mod-k.
|
|
-- Windows are either displayed full screen, tiled horizontally, or tiled
|
|
-- vertically. You can toggle the layout mode with mod-space, which will
|
|
-- cycle through the available modes.
|
|
--
|
|
-- You can switch to workspace N with mod-N. For example, to switch to
|
|
-- workspace 5, you would press mod-5. Similarly, you can move the current
|
|
-- window to another workspace with mod-shift-N.
|
|
--
|
|
-- When running with multiple monitors (Xinerama), each screen has exactly
|
|
-- 1 workspace visible. When xmonad starts, workspace 1 is on screen 1,
|
|
-- workspace 2 is on screen 2, etc. If you switch to a workspace which is
|
|
-- currently visible on another screen, xmonad simply switches focus to
|
|
-- that screen. If you switch to a workspace which is *not* visible, xmonad
|
|
-- replaces the workspace on the *current* screen with the workspace you
|
|
-- selected.
|
|
--
|
|
-- For example, if you have the following configuration:
|
|
--
|
|
-- Screen 1: Workspace 2
|
|
-- Screen 2: Workspace 5 (current workspace)
|
|
--
|
|
-- and you wanted to view workspace 7 on screen 1, you would press:
|
|
--
|
|
-- mod-2 (to select workspace 2, and make screen 1 the current screen)
|
|
-- mod-7 (to select workspace 7)
|
|
--
|
|
-- Since switching to the workspace currently visible on a given screen is
|
|
-- such a common operation, shortcuts are provided: mod-{w,e,r} switch to
|
|
-- the workspace currently visible on screens 1, 2, and 3 respectively.
|
|
-- Likewise, shift-mod-{w,e,r} moves the current window to the workspace on
|
|
-- that screen. Using these keys, the above example would become mod-w
|
|
-- mod-7.
|
|
--
|
|
|
|
--
|
|
-- Useful imports
|
|
--
|
|
import XMonad
|
|
import Operations
|
|
import Data.Ratio
|
|
import Data.Bits ((.|.))
|
|
import qualified Data.Map as M
|
|
import System.Exit
|
|
import Graphics.X11.Xlib
|
|
|
|
-- The number of workspaces (virtual screens)
|
|
workspaces :: Int
|
|
workspaces = 9
|
|
|
|
-- modMask lets you specify which modkey you want to use. The default is mod1Mask
|
|
-- ("left alt"). You may also consider using mod3Mask ("right alt"), which
|
|
-- does not conflict with emacs keybindings. The "windows key" is usually
|
|
-- mod4Mask.
|
|
--
|
|
modMask :: KeyMask
|
|
modMask = mod1Mask
|
|
|
|
-- When resizing a window, this ratio specifies by what percent to
|
|
-- resize in a single step
|
|
defaultDelta :: Rational
|
|
defaultDelta = 3%100
|
|
|
|
-- The default number of windows in the master area
|
|
defaultWindowsInMaster :: Int
|
|
defaultWindowsInMaster = 1
|
|
|
|
-- numlock handling:
|
|
--
|
|
-- The mask for the numlock key. You may need to change this on some systems.
|
|
--
|
|
-- You can find the numlock modifier by running "xmodmap" and looking for a
|
|
-- modifier with Num_Lock bound to it:
|
|
--
|
|
-- $ xmodmap | grep Num
|
|
-- mod2 Num_Lock (0x4d)
|
|
--
|
|
numlockMask :: KeyMask
|
|
numlockMask = mod2Mask
|
|
|
|
-- Border colors for unfocused and focused windows, respectively.
|
|
normalBorderColor, focusedBorderColor :: String
|
|
normalBorderColor = "#dddddd"
|
|
focusedBorderColor = "#ff0000"
|
|
|
|
-- Width of the window border in pixels
|
|
borderWidth :: Dimension
|
|
borderWidth = 1
|
|
|
|
-- The default set of Layouts:
|
|
defaultLayouts :: [Layout]
|
|
defaultLayouts = [ full,
|
|
tall defaultWindowsInMaster defaultDelta (1%2),
|
|
wide defaultWindowsInMaster defaultDelta (1%2) ]
|
|
|
|
--
|
|
-- The key bindings list.
|
|
--
|
|
keys :: M.Map (KeyMask, KeySym) (X ())
|
|
keys = M.fromList $
|
|
[ ((modMask .|. shiftMask, xK_Return), spawn "xterm")
|
|
, ((modMask, xK_p ), spawn "exe=`dmenu_path | dmenu` && exec $exe")
|
|
, ((modMask .|. shiftMask, xK_p ), spawn "gmrun")
|
|
, ((modMask, xK_space ), switchLayout)
|
|
|
|
-- 'nudge': resize viewed windows to the correct size.
|
|
, ((modMask, xK_n ), refresh)
|
|
|
|
, ((modMask, xK_Tab ), focusLeft)
|
|
, ((modMask, xK_j ), focusLeft)
|
|
, ((modMask, xK_k ), focusRight)
|
|
|
|
, ((modMask, xK_h ), sendMessage Shrink)
|
|
, ((modMask, xK_l ), sendMessage Expand)
|
|
|
|
, ((modMask .|. shiftMask, xK_j ), sendMessage (IncMasterN 1))
|
|
, ((modMask .|. shiftMask, xK_k ), sendMessage (IncMasterN (-1)))
|
|
|
|
, ((modMask .|. shiftMask, xK_c ), kill)
|
|
|
|
, ((modMask .|. shiftMask, xK_q ), io $ exitWith ExitSuccess)
|
|
, ((modMask .|. shiftMask .|. controlMask, xK_q ), io restart)
|
|
|
|
-- Cycle the current tiling order
|
|
, ((modMask, xK_Return), swap)
|
|
|
|
] ++
|
|
-- Keybindings to get to each workspace:
|
|
[((m .|. modMask, k), f i)
|
|
| (i, k) <- zip [0 .. fromIntegral workspaces - 1] [xK_1 ..]
|
|
, (f, m) <- [(view, 0), (shift, shiftMask)]]
|
|
|
|
-- Keybindings to each screen :
|
|
-- mod-wer (underneath 123) switches to physical/Xinerama screens 1 2 and 3
|
|
++
|
|
[((m .|. modMask, key), screenWorkspace sc >>= f)
|
|
| (key, sc) <- zip [xK_w, xK_e, xK_r] [0..]
|
|
, (f, m) <- [(view, 0), (shift, shiftMask)]]
|
|
|