Sophie

Sophie

distrib > Fedora > 18 > i386 > by-pkgid > 16551e78563a5b49ff9624ee1c8b8101 > files > 1221

ghc-xmonad-contrib-devel-0.11-1.1.fc18.i686.rpm

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html>
<head>
<!-- Generated by HsColour, http://code.haskell.org/~malcolm/hscolour/ -->
<title>XMonad/Actions/Navigation2D.hs</title>
<link type='text/css' rel='stylesheet' href='hscolour.css' />
</head>
<body>
<pre><a name="line-1"></a><span class='hs-comment'>{-# LANGUAGE DeriveDataTypeable, MultiParamTypeClasses, PatternGuards, RankNTypes, TypeSynonymInstances #-}</span>
<a name="line-2"></a>
<a name="line-3"></a><span class='hs-comment'>-----------------------------------------------------------------------------</span>
<a name="line-4"></a><span class='hs-comment'>-- |</span>
<a name="line-5"></a><span class='hs-comment'>-- Module      :  XMonad.Layout.Navigation2D</span>
<a name="line-6"></a><span class='hs-comment'>-- Copyright   :  (c) 2011  Norbert Zeh &lt;nzeh@cs.dal.ca&gt;</span>
<a name="line-7"></a><span class='hs-comment'>-- License     :  BSD3-style (see LICENSE)</span>
<a name="line-8"></a><span class='hs-comment'>--</span>
<a name="line-9"></a><span class='hs-comment'>-- Maintainer  :  Norbert Zeh &lt;nzeh@cs.dal.ca&gt;</span>
<a name="line-10"></a><span class='hs-comment'>-- Stability   :  unstable</span>
<a name="line-11"></a><span class='hs-comment'>-- Portability :  unportable</span>
<a name="line-12"></a><span class='hs-comment'>--</span>
<a name="line-13"></a><span class='hs-comment'>-- Navigation2D is an xmonad extension that allows easy directional</span>
<a name="line-14"></a><span class='hs-comment'>-- navigation of windows and screens (in a multi-monitor setup).</span>
<a name="line-15"></a><span class='hs-comment'>-----------------------------------------------------------------------------</span>
<a name="line-16"></a>
<a name="line-17"></a><span class='hs-keyword'>module</span> <span class='hs-conid'>XMonad</span><span class='hs-varop'>.</span><span class='hs-conid'>Actions</span><span class='hs-varop'>.</span><span class='hs-conid'>Navigation2D</span> <span class='hs-layout'>(</span> <span class='hs-comment'>-- * Usage</span>
<a name="line-18"></a>                                     <span class='hs-comment'>-- $usage</span>
<a name="line-19"></a>
<a name="line-20"></a>                                     <span class='hs-comment'>-- * Finer points</span>
<a name="line-21"></a>                                     <span class='hs-comment'>-- $finer_points</span>
<a name="line-22"></a>
<a name="line-23"></a>                                     <span class='hs-comment'>-- * Alternative directional navigation modules</span>
<a name="line-24"></a>                                     <span class='hs-comment'>-- $alternatives</span>
<a name="line-25"></a>
<a name="line-26"></a>                                     <span class='hs-comment'>-- * Incompatibilities</span>
<a name="line-27"></a>                                     <span class='hs-comment'>-- $incompatibilities</span>
<a name="line-28"></a>
<a name="line-29"></a>                                     <span class='hs-comment'>-- * Detailed technical discussion</span>
<a name="line-30"></a>                                     <span class='hs-comment'>-- $technical</span>
<a name="line-31"></a>
<a name="line-32"></a>                                     <span class='hs-comment'>-- * Exported functions and types</span>
<a name="line-33"></a>                                     <span class='hs-comment'>-- #Exports#</span>
<a name="line-34"></a>
<a name="line-35"></a>                                     <span class='hs-varid'>withNavigation2DConfig</span>
<a name="line-36"></a>                                   <span class='hs-layout'>,</span> <span class='hs-conid'>Navigation2DConfig</span><span class='hs-layout'>(</span><span class='hs-keyglyph'>..</span><span class='hs-layout'>)</span>
<a name="line-37"></a>                                   <span class='hs-layout'>,</span> <span class='hs-varid'>defaultNavigation2DConfig</span>
<a name="line-38"></a>                                   <span class='hs-layout'>,</span> <span class='hs-conid'>Navigation2D</span>
<a name="line-39"></a>                                   <span class='hs-layout'>,</span> <span class='hs-varid'>lineNavigation</span>
<a name="line-40"></a>                                   <span class='hs-layout'>,</span> <span class='hs-varid'>centerNavigation</span>
<a name="line-41"></a>                                   <span class='hs-layout'>,</span> <span class='hs-varid'>fullScreenRect</span>
<a name="line-42"></a>                                   <span class='hs-layout'>,</span> <span class='hs-varid'>singleWindowRect</span>
<a name="line-43"></a>                                   <span class='hs-layout'>,</span> <span class='hs-varid'>switchLayer</span>
<a name="line-44"></a>                                   <span class='hs-layout'>,</span> <span class='hs-varid'>windowGo</span>
<a name="line-45"></a>                                   <span class='hs-layout'>,</span> <span class='hs-varid'>windowSwap</span>
<a name="line-46"></a>                                   <span class='hs-layout'>,</span> <span class='hs-varid'>windowToScreen</span>
<a name="line-47"></a>                                   <span class='hs-layout'>,</span> <span class='hs-varid'>screenGo</span>
<a name="line-48"></a>                                   <span class='hs-layout'>,</span> <span class='hs-varid'>screenSwap</span>
<a name="line-49"></a>                                   <span class='hs-layout'>,</span> <span class='hs-conid'>Direction2D</span><span class='hs-layout'>(</span><span class='hs-keyglyph'>..</span><span class='hs-layout'>)</span>
<a name="line-50"></a>                                   <span class='hs-layout'>)</span> <span class='hs-keyword'>where</span>
<a name="line-51"></a>
<a name="line-52"></a><span class='hs-keyword'>import</span> <span class='hs-conid'>Control</span><span class='hs-varop'>.</span><span class='hs-conid'>Applicative</span>
<a name="line-53"></a><span class='hs-keyword'>import</span> <span class='hs-keyword'>qualified</span> <span class='hs-conid'>Data</span><span class='hs-varop'>.</span><span class='hs-conid'>List</span> <span class='hs-keyword'>as</span> <span class='hs-conid'>L</span>
<a name="line-54"></a><span class='hs-keyword'>import</span> <span class='hs-keyword'>qualified</span> <span class='hs-conid'>Data</span><span class='hs-varop'>.</span><span class='hs-conid'>Map</span> <span class='hs-keyword'>as</span> <span class='hs-conid'>M</span>
<a name="line-55"></a><span class='hs-keyword'>import</span> <span class='hs-conid'>Data</span><span class='hs-varop'>.</span><span class='hs-conid'>Maybe</span>
<a name="line-56"></a><span class='hs-keyword'>import</span> <span class='hs-conid'>XMonad</span> <span class='hs-varid'>hiding</span> <span class='hs-layout'>(</span><span class='hs-conid'>Screen</span><span class='hs-layout'>)</span>
<a name="line-57"></a><span class='hs-keyword'>import</span> <span class='hs-keyword'>qualified</span> <span class='hs-conid'>XMonad</span><span class='hs-varop'>.</span><span class='hs-conid'>StackSet</span> <span class='hs-keyword'>as</span> <span class='hs-conid'>W</span>
<a name="line-58"></a><span class='hs-keyword'>import</span> <span class='hs-keyword'>qualified</span> <span class='hs-conid'>XMonad</span><span class='hs-varop'>.</span><span class='hs-conid'>Util</span><span class='hs-varop'>.</span><span class='hs-conid'>ExtensibleState</span> <span class='hs-keyword'>as</span> <span class='hs-conid'>XS</span>
<a name="line-59"></a><span class='hs-keyword'>import</span> <span class='hs-conid'>XMonad</span><span class='hs-varop'>.</span><span class='hs-conid'>Util</span><span class='hs-varop'>.</span><span class='hs-conid'>Types</span>
<a name="line-60"></a>
<a name="line-61"></a><span class='hs-comment'>-- $usage</span>
<a name="line-62"></a><span class='hs-comment'>-- #Usage#</span>
<a name="line-63"></a><span class='hs-comment'>-- Navigation2D provides directional navigation (go left, right, up, down) for</span>
<a name="line-64"></a><span class='hs-comment'>-- windows and screens.  It treats floating and tiled windows as two separate</span>
<a name="line-65"></a><span class='hs-comment'>-- layers and provides mechanisms to navigate within each layer and to switch</span>
<a name="line-66"></a><span class='hs-comment'>-- between layers.  Navigation2D provides two different navigation strategies</span>
<a name="line-67"></a><span class='hs-comment'>-- (see &lt;#Technical_Discussion&gt; for details): /Line navigation/ feels rather</span>
<a name="line-68"></a><span class='hs-comment'>-- natural but may make it impossible to navigate to a given window from the</span>
<a name="line-69"></a><span class='hs-comment'>-- current window, particularly in the floating layer.  /Center navigation/</span>
<a name="line-70"></a><span class='hs-comment'>-- feels less natural in certain situations but ensures that all windows can be</span>
<a name="line-71"></a><span class='hs-comment'>-- reached without the need to involve the mouse.  Navigation2D allows different</span>
<a name="line-72"></a><span class='hs-comment'>-- navigation strategies to be used in the two layers and allows customization</span>
<a name="line-73"></a><span class='hs-comment'>-- of the navigation strategy for the tiled layer based on the layout currently</span>
<a name="line-74"></a><span class='hs-comment'>-- in effect.</span>
<a name="line-75"></a><span class='hs-comment'>--</span>
<a name="line-76"></a><span class='hs-comment'>-- You can use this module with (a subset of) the following in your @~\/.xmonad\/xmonad.hs@:</span>
<a name="line-77"></a><span class='hs-comment'>--</span>
<a name="line-78"></a><span class='hs-comment'>-- &gt; import XMonad.Actions.Navigation2D</span>
<a name="line-79"></a><span class='hs-comment'>--</span>
<a name="line-80"></a><span class='hs-comment'>-- Then edit your keybindings:</span>
<a name="line-81"></a><span class='hs-comment'>--</span>
<a name="line-82"></a><span class='hs-comment'>-- &gt;    -- Switch between layers</span>
<a name="line-83"></a><span class='hs-comment'>-- &gt;    , ((modm,                 xK_space), switchLayers)</span>
<a name="line-84"></a><span class='hs-comment'>-- &gt;</span>
<a name="line-85"></a><span class='hs-comment'>-- &gt;    -- Directional navigation of windows</span>
<a name="line-86"></a><span class='hs-comment'>-- &gt;    , ((modm,                 xK_Right), windowGo R False)</span>
<a name="line-87"></a><span class='hs-comment'>-- &gt;    , ((modm,                 xK_Left ), windowGo L False)</span>
<a name="line-88"></a><span class='hs-comment'>-- &gt;    , ((modm,                 xK_Up   ), windowGo U False)</span>
<a name="line-89"></a><span class='hs-comment'>-- &gt;    , ((modm,                 xK_Down ), windowGo D False)</span>
<a name="line-90"></a><span class='hs-comment'>-- &gt;</span>
<a name="line-91"></a><span class='hs-comment'>-- &gt;    -- Swap adjacent windows</span>
<a name="line-92"></a><span class='hs-comment'>-- &gt;    , ((modm .|. controlMask, xK_Right), windowSwap R False)</span>
<a name="line-93"></a><span class='hs-comment'>-- &gt;    , ((modm .|. controlMask, xK_Left ), windowSwap L False)</span>
<a name="line-94"></a><span class='hs-comment'>-- &gt;    , ((modm .|. controlMask, xK_Up   ), windowSwap U False)</span>
<a name="line-95"></a><span class='hs-comment'>-- &gt;    , ((modm .|. controlMask, xK_Down ), windowSwap D False)</span>
<a name="line-96"></a><span class='hs-comment'>-- &gt;</span>
<a name="line-97"></a><span class='hs-comment'>-- &gt;    -- Directional navigation of screens</span>
<a name="line-98"></a><span class='hs-comment'>-- &gt;    , ((modm,                 xK_r    ), screenGo R False)</span>
<a name="line-99"></a><span class='hs-comment'>-- &gt;    , ((modm,                 xK_l    ), screenGo L False)</span>
<a name="line-100"></a><span class='hs-comment'>-- &gt;    , ((modm,                 xK_u    ), screenGo U False)</span>
<a name="line-101"></a><span class='hs-comment'>-- &gt;    , ((modm,                 xK_d    ), screenGo D False)</span>
<a name="line-102"></a><span class='hs-comment'>-- &gt;</span>
<a name="line-103"></a><span class='hs-comment'>-- &gt;    -- Swap workspaces on adjacent screens</span>
<a name="line-104"></a><span class='hs-comment'>-- &gt;    , ((modm .|. controlMask, xK_r    ), screenSwap R False)</span>
<a name="line-105"></a><span class='hs-comment'>-- &gt;    , ((modm .|. controlMask, xK_l    ), screenSwap L False)</span>
<a name="line-106"></a><span class='hs-comment'>-- &gt;    , ((modm .|. controlMask, xK_u    ), screenSwap U False)</span>
<a name="line-107"></a><span class='hs-comment'>-- &gt;    , ((modm .|. controlMask, xK_d    ), screenSwap D False)</span>
<a name="line-108"></a><span class='hs-comment'>-- &gt;</span>
<a name="line-109"></a><span class='hs-comment'>-- &gt;    -- Send window to adjacent screen</span>
<a name="line-110"></a><span class='hs-comment'>-- &gt;    , ((modm .|. mod1Mask,    xK_r    ), windowToScreen R False)</span>
<a name="line-111"></a><span class='hs-comment'>-- &gt;    , ((modm .|. mod1Mask,    xK_l    ), windowToScreen L False)</span>
<a name="line-112"></a><span class='hs-comment'>-- &gt;    , ((modm .|. mod1Mask,    xK_u    ), windowToScreen U False)</span>
<a name="line-113"></a><span class='hs-comment'>-- &gt;    , ((modm .|. mod1Mask,    xK_d    ), windowToScreen D False)</span>
<a name="line-114"></a><span class='hs-comment'>--</span>
<a name="line-115"></a><span class='hs-comment'>-- and add the configuration of the module to your main function:</span>
<a name="line-116"></a><span class='hs-comment'>--</span>
<a name="line-117"></a><span class='hs-comment'>-- &gt; main = xmonad $ withNavigation2DConfig defaultNavigation2DConfig</span>
<a name="line-118"></a><span class='hs-comment'>-- &gt;               $ defaultConfig</span>
<a name="line-119"></a><span class='hs-comment'>--</span>
<a name="line-120"></a><span class='hs-comment'>-- For detailed instruction on editing the key binding see:</span>
<a name="line-121"></a><span class='hs-comment'>--</span>
<a name="line-122"></a><span class='hs-comment'>-- "XMonad.Doc.Extending#Editing_key_bindings".</span>
<a name="line-123"></a>
<a name="line-124"></a><span class='hs-comment'>-- $finer_points</span>
<a name="line-125"></a><span class='hs-comment'>-- #Finer_Points#</span>
<a name="line-126"></a><span class='hs-comment'>-- The above should get you started.  Here are some finer points:</span>
<a name="line-127"></a><span class='hs-comment'>--</span>
<a name="line-128"></a><span class='hs-comment'>-- Navigation2D has the ability to wrap around at screen edges.  For example, if</span>
<a name="line-129"></a><span class='hs-comment'>-- you navigated to the rightmost window on the rightmost screen and you</span>
<a name="line-130"></a><span class='hs-comment'>-- continued to go right, this would get you to the leftmost window on the</span>
<a name="line-131"></a><span class='hs-comment'>-- leftmost screen.  This feature may be useful for switching between screens</span>
<a name="line-132"></a><span class='hs-comment'>-- that are far apart but may be confusing at least to novice users.  Therefore,</span>
<a name="line-133"></a><span class='hs-comment'>-- it is disabled in the above example (e.g., navigation beyond the rightmost</span>
<a name="line-134"></a><span class='hs-comment'>-- window on the rightmost screen is not possible and trying to do so will</span>
<a name="line-135"></a><span class='hs-comment'>-- simply not do anything.)  If you want this feature, change all the 'False'</span>
<a name="line-136"></a><span class='hs-comment'>-- values in the above example to 'True'.  You could also decide you want</span>
<a name="line-137"></a><span class='hs-comment'>-- wrapping only for a subset of the operations and no wrapping for others.</span>
<a name="line-138"></a><span class='hs-comment'>--</span>
<a name="line-139"></a><span class='hs-comment'>-- By default, all layouts use the 'defaultTiledNavigation' strategy specified</span>
<a name="line-140"></a><span class='hs-comment'>-- in the 'Navigation2DConfig' (by default, line navigation is used).  To</span>
<a name="line-141"></a><span class='hs-comment'>-- override this behaviour for some layouts, add a pair (\"layout name\",</span>
<a name="line-142"></a><span class='hs-comment'>-- navigation strategy) to the 'layoutNavigation' list in the</span>
<a name="line-143"></a><span class='hs-comment'>-- 'Navigation2DConfig', where \"layout name\" is the string reported by the</span>
<a name="line-144"></a><span class='hs-comment'>-- layout's description method (normally what is shown as the layout name in</span>
<a name="line-145"></a><span class='hs-comment'>-- your status bar).  For example, all navigation strategies normally allow only</span>
<a name="line-146"></a><span class='hs-comment'>-- navigation between mapped windows.  The first step to overcome this, for</span>
<a name="line-147"></a><span class='hs-comment'>-- example, for the Full layout, is to switch to center navigation for the Full</span>
<a name="line-148"></a><span class='hs-comment'>-- layout:</span>
<a name="line-149"></a><span class='hs-comment'>--</span>
<a name="line-150"></a><span class='hs-comment'>-- &gt; myNavigation2DConfig = defaultNavigation2DConfig { layoutNavigation = [("Full", centerNavigation)] }</span>
<a name="line-151"></a><span class='hs-comment'>-- &gt;</span>
<a name="line-152"></a><span class='hs-comment'>-- &gt; main = xmonad $ withNavigation2DConfig myNavigation2DConfig</span>
<a name="line-153"></a><span class='hs-comment'>-- &gt;               $ defaultConfig</span>
<a name="line-154"></a><span class='hs-comment'>--</span>
<a name="line-155"></a><span class='hs-comment'>-- The navigation between windows is based on their screen rectangles, which are</span>
<a name="line-156"></a><span class='hs-comment'>-- available /and meaningful/ only for mapped windows.  Thus, as already said,</span>
<a name="line-157"></a><span class='hs-comment'>-- the default is to allow navigation only between mapped windows.  However,</span>
<a name="line-158"></a><span class='hs-comment'>-- there are layouts that do not keep all windows mapped.  One example is the</span>
<a name="line-159"></a><span class='hs-comment'>-- Full layout, which unmaps all windows except the one that has the focus,</span>
<a name="line-160"></a><span class='hs-comment'>-- thereby preventing navigation to any other window in the layout.  To make</span>
<a name="line-161"></a><span class='hs-comment'>-- navigation to unmapped windows possible, unmapped windows need to be assigned</span>
<a name="line-162"></a><span class='hs-comment'>-- rectangles to pretend they are mapped, and a natural way to do this for the</span>
<a name="line-163"></a><span class='hs-comment'>-- Full layout is to pretend all windows occupy the full screen and are stacked</span>
<a name="line-164"></a><span class='hs-comment'>-- on top of each other so that only the frontmost one is visible.  This can be</span>
<a name="line-165"></a><span class='hs-comment'>-- done as follows:</span>
<a name="line-166"></a><span class='hs-comment'>--</span>
<a name="line-167"></a><span class='hs-comment'>-- &gt; myNavigation2DConfig = defaultNavigation2DConfig { layoutNavigation   = [("Full", centerNavigation)]</span>
<a name="line-168"></a><span class='hs-comment'>-- &gt;                                                  , unmappedWindowRect = [("Full", singleWindowRect)]</span>
<a name="line-169"></a><span class='hs-comment'>-- &gt;                                                  }</span>
<a name="line-170"></a><span class='hs-comment'>-- &gt;</span>
<a name="line-171"></a><span class='hs-comment'>-- &gt; main = xmonad $ withNavigation2DConfig myNavigation2DConfig</span>
<a name="line-172"></a><span class='hs-comment'>-- &gt;               $ defaultConfig</span>
<a name="line-173"></a><span class='hs-comment'>--</span>
<a name="line-174"></a><span class='hs-comment'>-- With this setup, Left/Up navigation behaves like standard</span>
<a name="line-175"></a><span class='hs-comment'>-- 'XMonad.StackSet.focusUp' and Right/Down navigation behaves like</span>
<a name="line-176"></a><span class='hs-comment'>-- 'XMonad.StackSet.focusDown', thus allowing navigation between windows in the</span>
<a name="line-177"></a><span class='hs-comment'>-- layout.</span>
<a name="line-178"></a><span class='hs-comment'>--</span>
<a name="line-179"></a><span class='hs-comment'>-- In general, each entry in the 'unmappedWindowRect' association list is a pair</span>
<a name="line-180"></a><span class='hs-comment'>-- (\"layout description\", function), where the function computes a rectangle</span>
<a name="line-181"></a><span class='hs-comment'>-- for each unmapped window from the screen it is on and the window ID.</span>
<a name="line-182"></a><span class='hs-comment'>-- Currently, Navigation2D provides only two functions of this type:</span>
<a name="line-183"></a><span class='hs-comment'>-- 'singleWindowRect' and 'fullScreenRect'.</span>
<a name="line-184"></a><span class='hs-comment'>--</span>
<a name="line-185"></a><span class='hs-comment'>-- With per-layout navigation strategies, if different layouts are in effect on</span>
<a name="line-186"></a><span class='hs-comment'>-- different screens in a multi-monitor setup, and different navigation</span>
<a name="line-187"></a><span class='hs-comment'>-- strategies are defined for these active layouts, the most general of these</span>
<a name="line-188"></a><span class='hs-comment'>-- navigation strategies is used across all screens (because Navigation2D does</span>
<a name="line-189"></a><span class='hs-comment'>-- not distinguish between windows on different workspaces), where center</span>
<a name="line-190"></a><span class='hs-comment'>-- navigation is more general than line navigation, as discussed formally under</span>
<a name="line-191"></a><span class='hs-comment'>-- &lt;#Technical_Discussion&gt;.</span>
<a name="line-192"></a>
<a name="line-193"></a><span class='hs-comment'>-- $alternatives</span>
<a name="line-194"></a><span class='hs-comment'>-- #Alternatives#</span>
<a name="line-195"></a><span class='hs-comment'>--</span>
<a name="line-196"></a><span class='hs-comment'>-- There exist two alternatives to Navigation2D:</span>
<a name="line-197"></a><span class='hs-comment'>-- "XMonad.Actions.WindowNavigation" and "XMonad.Layout.WindowNavigation".</span>
<a name="line-198"></a><span class='hs-comment'>-- X.L.WindowNavigation has the advantage of colouring windows to indicate the</span>
<a name="line-199"></a><span class='hs-comment'>-- window that would receive the focus in each navigation direction, but it does</span>
<a name="line-200"></a><span class='hs-comment'>-- not support navigation across multiple monitors, does not support directional</span>
<a name="line-201"></a><span class='hs-comment'>-- navigation of floating windows, and has a very unintuitive definition of</span>
<a name="line-202"></a><span class='hs-comment'>-- which window receives the focus next in each direction.  X.A.WindowNavigation</span>
<a name="line-203"></a><span class='hs-comment'>-- does support navigation across multiple monitors but does not provide window</span>
<a name="line-204"></a><span class='hs-comment'>-- colouring while retaining the unintuitive navigational semantics of</span>
<a name="line-205"></a><span class='hs-comment'>-- X.L.WindowNavigation.  This makes it very difficult to predict which window</span>
<a name="line-206"></a><span class='hs-comment'>-- receives the focus next.  Neither X.A.WindowNavigation nor</span>
<a name="line-207"></a><span class='hs-comment'>-- X.L.WindowNavigation supports directional navigation of screens.</span>
<a name="line-208"></a>
<a name="line-209"></a><span class='hs-comment'>-- $technical</span>
<a name="line-210"></a><span class='hs-comment'>-- #Technical_Discussion#</span>
<a name="line-211"></a><span class='hs-comment'>-- An in-depth discussion of the navigational strategies implemented in</span>
<a name="line-212"></a><span class='hs-comment'>-- Navigation2D, including formal proofs of their properties, can be found</span>
<a name="line-213"></a><span class='hs-comment'>-- at &lt;<a href="http://www.cs.dal.ca/~nzeh/xmonad/Navigation2D.pdf">http://www.cs.dal.ca/~nzeh/xmonad/Navigation2D.pdf</a>&gt;.</span>
<a name="line-214"></a>
<a name="line-215"></a><span class='hs-comment'>-- $incompatibilities</span>
<a name="line-216"></a><span class='hs-comment'>-- #Incompatibilities#</span>
<a name="line-217"></a><span class='hs-comment'>-- Currently Navigation2D is known not to play nicely with tabbed layouts, but</span>
<a name="line-218"></a><span class='hs-comment'>-- it should work well with any other tiled layout.  My hope is to address the</span>
<a name="line-219"></a><span class='hs-comment'>-- incompatibility with tabbed layouts in a future version.  The navigation to</span>
<a name="line-220"></a><span class='hs-comment'>-- unmapped windows, for example in a Full layout, by assigning rectangles to</span>
<a name="line-221"></a><span class='hs-comment'>-- unmapped windows is more a workaround than a clean solution.  Figuring out</span>
<a name="line-222"></a><span class='hs-comment'>-- how to deal with tabbed layouts may also lead to a more general and cleaner</span>
<a name="line-223"></a><span class='hs-comment'>-- solution to query the layout for a window's rectangle that may make this</span>
<a name="line-224"></a><span class='hs-comment'>-- workaround unnecessary.  At that point, the 'unmappedWindowRect' field of the</span>
<a name="line-225"></a><span class='hs-comment'>-- 'Navigation2DConfig' will disappear.</span>
<a name="line-226"></a>
<a name="line-227"></a><a name="Rect"></a><span class='hs-comment'>-- | A rectangle paired with an object</span>
<a name="line-228"></a><a name="Rect"></a><span class='hs-keyword'>type</span> <span class='hs-conid'>Rect</span> <span class='hs-varid'>a</span> <span class='hs-keyglyph'>=</span> <span class='hs-layout'>(</span><span class='hs-varid'>a</span><span class='hs-layout'>,</span> <span class='hs-conid'>Rectangle</span><span class='hs-layout'>)</span>
<a name="line-229"></a>
<a name="line-230"></a><a name="WinRect"></a><span class='hs-comment'>-- | A shorthand for window-rectangle pairs.  Reduces typing.</span>
<a name="line-231"></a><a name="WinRect"></a><span class='hs-keyword'>type</span> <span class='hs-conid'>WinRect</span> <span class='hs-keyglyph'>=</span> <span class='hs-conid'>Rect</span> <span class='hs-conid'>Window</span>
<a name="line-232"></a>
<a name="line-233"></a><a name="WSRect"></a><span class='hs-comment'>-- | A shorthand for workspace-rectangle pairs.  Reduces typing.</span>
<a name="line-234"></a><a name="WSRect"></a><span class='hs-keyword'>type</span> <span class='hs-conid'>WSRect</span> <span class='hs-keyglyph'>=</span> <span class='hs-conid'>Rect</span> <span class='hs-conid'>WorkspaceId</span>
<a name="line-235"></a>
<a name="line-236"></a><span class='hs-comment'>----------------------------------------------------------------------------------------------------</span>
<a name="line-237"></a><span class='hs-comment'>----------------------------------------------------------------------------------------------------</span>
<a name="line-238"></a><span class='hs-comment'>--                                                                                                --</span>
<a name="line-239"></a><span class='hs-comment'>--                                        PUBLIC INTERFACE                                        --</span>
<a name="line-240"></a><span class='hs-comment'>--                                                                                                --</span>
<a name="line-241"></a><span class='hs-comment'>----------------------------------------------------------------------------------------------------</span>
<a name="line-242"></a><span class='hs-comment'>----------------------------------------------------------------------------------------------------</span>
<a name="line-243"></a>
<a name="line-244"></a><a name="Navigation2D"></a><span class='hs-comment'>-- | Encapsulates the navigation strategy</span>
<a name="line-245"></a><a name="Navigation2D"></a><span class='hs-keyword'>data</span> <span class='hs-conid'>Navigation2D</span> <span class='hs-keyglyph'>=</span> <span class='hs-conid'>N</span> <span class='hs-conid'>Generality</span> <span class='hs-layout'>(</span><span class='hs-keyword'>forall</span> <span class='hs-varid'>a</span> <span class='hs-varop'>.</span> <span class='hs-conid'>Eq</span> <span class='hs-varid'>a</span> <span class='hs-keyglyph'>=&gt;</span> <span class='hs-conid'>Direction2D</span> <span class='hs-keyglyph'>-&gt;</span> <span class='hs-conid'>Rect</span> <span class='hs-varid'>a</span> <span class='hs-keyglyph'>-&gt;</span> <span class='hs-keyglyph'>[</span><span class='hs-conid'>Rect</span> <span class='hs-varid'>a</span><span class='hs-keyglyph'>]</span> <span class='hs-keyglyph'>-&gt;</span> <span class='hs-conid'>Maybe</span> <span class='hs-varid'>a</span><span class='hs-layout'>)</span>
<a name="line-246"></a>
<a name="line-247"></a><a name="runNav"></a><span class='hs-definition'>runNav</span> <span class='hs-keyglyph'>::</span> <span class='hs-keyword'>forall</span> <span class='hs-varid'>a</span> <span class='hs-varop'>.</span> <span class='hs-conid'>Eq</span> <span class='hs-varid'>a</span> <span class='hs-keyglyph'>=&gt;</span> <span class='hs-conid'>Navigation2D</span> <span class='hs-keyglyph'>-&gt;</span> <span class='hs-layout'>(</span><span class='hs-conid'>Direction2D</span> <span class='hs-keyglyph'>-&gt;</span> <span class='hs-conid'>Rect</span> <span class='hs-varid'>a</span> <span class='hs-keyglyph'>-&gt;</span> <span class='hs-keyglyph'>[</span><span class='hs-conid'>Rect</span> <span class='hs-varid'>a</span><span class='hs-keyglyph'>]</span> <span class='hs-keyglyph'>-&gt;</span> <span class='hs-conid'>Maybe</span> <span class='hs-varid'>a</span><span class='hs-layout'>)</span>
<a name="line-248"></a><span class='hs-definition'>runNav</span> <span class='hs-layout'>(</span><span class='hs-conid'>N</span> <span class='hs-keyword'>_</span> <span class='hs-varid'>nav</span><span class='hs-layout'>)</span> <span class='hs-keyglyph'>=</span> <span class='hs-varid'>nav</span>
<a name="line-249"></a>
<a name="line-250"></a><a name="Generality"></a><span class='hs-comment'>-- | Score that indicates how general a navigation strategy is</span>
<a name="line-251"></a><a name="Generality"></a><span class='hs-keyword'>type</span> <span class='hs-conid'>Generality</span> <span class='hs-keyglyph'>=</span> <span class='hs-conid'>Int</span>
<a name="line-252"></a>
<a name="line-253"></a><a name="instance%20Eq%20Navigation2D"></a><span class='hs-keyword'>instance</span> <span class='hs-conid'>Eq</span> <span class='hs-conid'>Navigation2D</span> <span class='hs-keyword'>where</span>
<a name="line-254"></a>  <span class='hs-layout'>(</span><span class='hs-conid'>N</span> <span class='hs-varid'>x</span> <span class='hs-keyword'>_</span><span class='hs-layout'>)</span> <span class='hs-varop'>==</span> <span class='hs-layout'>(</span><span class='hs-conid'>N</span> <span class='hs-varid'>y</span> <span class='hs-keyword'>_</span><span class='hs-layout'>)</span> <span class='hs-keyglyph'>=</span> <span class='hs-varid'>x</span> <span class='hs-varop'>==</span> <span class='hs-varid'>y</span>
<a name="line-255"></a>
<a name="line-256"></a><a name="instance%20Ord%20Navigation2D"></a><span class='hs-keyword'>instance</span> <span class='hs-conid'>Ord</span> <span class='hs-conid'>Navigation2D</span> <span class='hs-keyword'>where</span>
<a name="line-257"></a>  <span class='hs-layout'>(</span><span class='hs-conid'>N</span> <span class='hs-varid'>x</span> <span class='hs-keyword'>_</span><span class='hs-layout'>)</span> <span class='hs-varop'>&lt;=</span> <span class='hs-layout'>(</span><span class='hs-conid'>N</span> <span class='hs-varid'>y</span> <span class='hs-keyword'>_</span><span class='hs-layout'>)</span> <span class='hs-keyglyph'>=</span> <span class='hs-varid'>x</span> <span class='hs-varop'>&lt;=</span> <span class='hs-varid'>y</span>
<a name="line-258"></a>
<a name="line-259"></a><a name="lineNavigation"></a><span class='hs-comment'>-- | Line navigation.  To illustrate this navigation strategy, consider</span>
<a name="line-260"></a><span class='hs-comment'>-- navigating to the left from the current window.  In this case, we draw a</span>
<a name="line-261"></a><span class='hs-comment'>-- horizontal line through the center of the current window and consider all</span>
<a name="line-262"></a><span class='hs-comment'>-- windows that intersect this horizontal line and whose right boundaries are to</span>
<a name="line-263"></a><span class='hs-comment'>-- the left of the left boundary of the current window.  From among these</span>
<a name="line-264"></a><span class='hs-comment'>-- windows, we choose the one with the rightmost right boundary.</span>
<a name="line-265"></a><span class='hs-definition'>lineNavigation</span> <span class='hs-keyglyph'>::</span> <span class='hs-conid'>Navigation2D</span>
<a name="line-266"></a><span class='hs-definition'>lineNavigation</span> <span class='hs-keyglyph'>=</span> <span class='hs-conid'>N</span> <span class='hs-num'>1</span> <span class='hs-varid'>doLineNavigation</span>
<a name="line-267"></a>
<a name="line-268"></a><a name="centerNavigation"></a><span class='hs-comment'>-- | Center navigation.  Again, consider navigating to the left.  Then we</span>
<a name="line-269"></a><span class='hs-comment'>-- consider the cone bounded by the two rays shot at 45-degree angles in</span>
<a name="line-270"></a><span class='hs-comment'>-- north-west and south-west direction from the center of the current window.  A</span>
<a name="line-271"></a><span class='hs-comment'>-- window is a candidate to receive the focus if its center lies in this cone.</span>
<a name="line-272"></a><span class='hs-comment'>-- We choose the window whose center has minimum L1-distance from the current</span>
<a name="line-273"></a><span class='hs-comment'>-- window center.  The tie breaking strategy for windows with the same distance</span>
<a name="line-274"></a><span class='hs-comment'>-- is a bit complicated (see &lt;#Technical_Discussion&gt;) but ensures that all</span>
<a name="line-275"></a><span class='hs-comment'>-- windows can be reached and that windows with the same center are traversed in</span>
<a name="line-276"></a><span class='hs-comment'>-- their order in the window stack, that is, in the order</span>
<a name="line-277"></a><span class='hs-comment'>-- 'XMonad.StackSet.focusUp' and 'XMonad.StackSet.focusDown' would traverse</span>
<a name="line-278"></a><span class='hs-comment'>-- them.</span>
<a name="line-279"></a><span class='hs-definition'>centerNavigation</span> <span class='hs-keyglyph'>::</span> <span class='hs-conid'>Navigation2D</span>
<a name="line-280"></a><span class='hs-definition'>centerNavigation</span> <span class='hs-keyglyph'>=</span> <span class='hs-conid'>N</span> <span class='hs-num'>2</span> <span class='hs-varid'>doCenterNavigation</span>
<a name="line-281"></a>
<a name="line-282"></a><a name="Navigation2DConfig"></a><span class='hs-comment'>-- | Stores the configuration of directional navigation</span>
<a name="line-283"></a><a name="Navigation2DConfig"></a><span class='hs-keyword'>data</span> <span class='hs-conid'>Navigation2DConfig</span> <span class='hs-keyglyph'>=</span> <span class='hs-conid'>Navigation2DConfig</span>
<a name="line-284"></a>  <span class='hs-layout'>{</span> <span class='hs-varid'>defaultTiledNavigation</span> <span class='hs-keyglyph'>::</span> <span class='hs-conid'>Navigation2D</span>             <span class='hs-comment'>-- ^ default navigation strategy for the tiled layer</span>
<a name="line-285"></a>  <span class='hs-layout'>,</span> <span class='hs-varid'>floatNavigation</span>        <span class='hs-keyglyph'>::</span> <span class='hs-conid'>Navigation2D</span>             <span class='hs-comment'>-- ^ navigation strategy for the float layer</span>
<a name="line-286"></a>  <span class='hs-layout'>,</span> <span class='hs-varid'>screenNavigation</span>       <span class='hs-keyglyph'>::</span> <span class='hs-conid'>Navigation2D</span>             <span class='hs-comment'>-- ^ strategy for navigation between screens</span>
<a name="line-287"></a>  <span class='hs-layout'>,</span> <span class='hs-varid'>layoutNavigation</span>       <span class='hs-keyglyph'>::</span> <span class='hs-keyglyph'>[</span><span class='hs-layout'>(</span><span class='hs-conid'>String</span><span class='hs-layout'>,</span> <span class='hs-conid'>Navigation2D</span><span class='hs-layout'>)</span><span class='hs-keyglyph'>]</span> <span class='hs-comment'>-- ^ association list of customized navigation strategies</span>
<a name="line-288"></a>                                                       <span class='hs-comment'>-- for different layouts in the tiled layer.  Each pair</span>
<a name="line-289"></a>                                                       <span class='hs-comment'>-- is of the form (\"layout description\", navigation</span>
<a name="line-290"></a>                                                       <span class='hs-comment'>-- strategy).  If there is no pair in this list whose first</span>
<a name="line-291"></a>                                                       <span class='hs-comment'>-- component is the name of the current layout, the</span>
<a name="line-292"></a>                                                       <span class='hs-comment'>-- 'defaultTiledNavigation' strategy is used.</span>
<a name="line-293"></a>  <span class='hs-layout'>,</span> <span class='hs-varid'>unmappedWindowRect</span>     <span class='hs-keyglyph'>::</span> <span class='hs-keyglyph'>[</span><span class='hs-layout'>(</span><span class='hs-conid'>String</span><span class='hs-layout'>,</span> <span class='hs-conid'>Screen</span> <span class='hs-keyglyph'>-&gt;</span> <span class='hs-conid'>Window</span> <span class='hs-keyglyph'>-&gt;</span> <span class='hs-conid'>X</span> <span class='hs-layout'>(</span><span class='hs-conid'>Maybe</span> <span class='hs-conid'>Rectangle</span><span class='hs-layout'>)</span><span class='hs-layout'>)</span><span class='hs-keyglyph'>]</span>
<a name="line-294"></a>                                                       <span class='hs-comment'>-- ^ list associating functions to calculate rectangles</span>
<a name="line-295"></a>                                                       <span class='hs-comment'>-- for unmapped windows with layouts to which they are</span>
<a name="line-296"></a>                                                       <span class='hs-comment'>-- to be applied.  Each pair in this list is of</span>
<a name="line-297"></a>                                                       <span class='hs-comment'>-- the form (\"layout description\", function), where the</span>
<a name="line-298"></a>                                                       <span class='hs-comment'>-- function calculates a rectangle for a given unmapped</span>
<a name="line-299"></a>                                                       <span class='hs-comment'>-- window from the screen it is on and its window ID.</span>
<a name="line-300"></a>                                                       <span class='hs-comment'>-- See &lt;#Finer_Points&gt; for how to use this.</span>
<a name="line-301"></a>  <span class='hs-layout'>}</span> <span class='hs-keyword'>deriving</span> <span class='hs-conid'>Typeable</span>
<a name="line-302"></a>
<a name="line-303"></a><a name="Screen"></a><span class='hs-comment'>-- | Shorthand for the tedious screen type</span>
<a name="line-304"></a><a name="Screen"></a><span class='hs-keyword'>type</span> <span class='hs-conid'>Screen</span> <span class='hs-keyglyph'>=</span> <span class='hs-conid'>W</span><span class='hs-varop'>.</span><span class='hs-conid'>Screen</span> <span class='hs-conid'>WorkspaceId</span> <span class='hs-layout'>(</span><span class='hs-conid'>Layout</span> <span class='hs-conid'>Window</span><span class='hs-layout'>)</span> <span class='hs-conid'>Window</span> <span class='hs-conid'>ScreenId</span> <span class='hs-conid'>ScreenDetail</span>
<a name="line-305"></a>
<a name="line-306"></a><a name="instance%20ExtensionClass%20Navigation2DConfig"></a><span class='hs-comment'>-- So we can store the configuration in extensible state</span>
<a name="line-307"></a><a name="instance%20ExtensionClass%20Navigation2DConfig"></a><span class='hs-keyword'>instance</span> <span class='hs-conid'>ExtensionClass</span> <span class='hs-conid'>Navigation2DConfig</span> <span class='hs-keyword'>where</span>
<a name="line-308"></a>  <span class='hs-varid'>initialValue</span> <span class='hs-keyglyph'>=</span> <span class='hs-varid'>defaultNavigation2DConfig</span>
<a name="line-309"></a>
<a name="line-310"></a><a name="withNavigation2DConfig"></a><span class='hs-comment'>-- | Modifies the xmonad configuration to store the Navigation2D configuration</span>
<a name="line-311"></a><span class='hs-definition'>withNavigation2DConfig</span> <span class='hs-keyglyph'>::</span> <span class='hs-conid'>Navigation2DConfig</span> <span class='hs-keyglyph'>-&gt;</span> <span class='hs-conid'>XConfig</span> <span class='hs-varid'>a</span> <span class='hs-keyglyph'>-&gt;</span> <span class='hs-conid'>XConfig</span> <span class='hs-varid'>a</span>
<a name="line-312"></a><span class='hs-definition'>withNavigation2DConfig</span> <span class='hs-varid'>conf2d</span> <span class='hs-varid'>xconf</span> <span class='hs-keyglyph'>=</span> <span class='hs-varid'>xconf</span> <span class='hs-layout'>{</span> <span class='hs-varid'>startupHook</span>  <span class='hs-keyglyph'>=</span> <span class='hs-varid'>startupHook</span> <span class='hs-varid'>xconf</span>
<a name="line-313"></a>                                                          <span class='hs-varop'>&gt;&gt;</span> <span class='hs-conid'>XS</span><span class='hs-varop'>.</span><span class='hs-varid'>put</span> <span class='hs-varid'>conf2d</span>
<a name="line-314"></a>                                            <span class='hs-layout'>}</span>
<a name="line-315"></a>
<a name="line-316"></a><a name="defaultNavigation2DConfig"></a><span class='hs-comment'>-- | Default navigation configuration.  It uses line navigation for the tiled</span>
<a name="line-317"></a><span class='hs-comment'>-- layer and for navigation between screens, and center navigation for the float</span>
<a name="line-318"></a><span class='hs-comment'>-- layer.  No custom navigation strategies or rectangles for unmapped windows are</span>
<a name="line-319"></a><span class='hs-comment'>-- defined for individual layouts.</span>
<a name="line-320"></a><span class='hs-definition'>defaultNavigation2DConfig</span> <span class='hs-keyglyph'>::</span> <span class='hs-conid'>Navigation2DConfig</span>
<a name="line-321"></a><span class='hs-definition'>defaultNavigation2DConfig</span> <span class='hs-keyglyph'>=</span> <span class='hs-conid'>Navigation2DConfig</span> <span class='hs-layout'>{</span> <span class='hs-varid'>defaultTiledNavigation</span> <span class='hs-keyglyph'>=</span> <span class='hs-varid'>lineNavigation</span>
<a name="line-322"></a>                                               <span class='hs-layout'>,</span> <span class='hs-varid'>floatNavigation</span>        <span class='hs-keyglyph'>=</span> <span class='hs-varid'>centerNavigation</span>
<a name="line-323"></a>                                               <span class='hs-layout'>,</span> <span class='hs-varid'>screenNavigation</span>       <span class='hs-keyglyph'>=</span> <span class='hs-varid'>lineNavigation</span>
<a name="line-324"></a>                                               <span class='hs-layout'>,</span> <span class='hs-varid'>layoutNavigation</span>       <span class='hs-keyglyph'>=</span> <span class='hs-conid'>[]</span>
<a name="line-325"></a>                                               <span class='hs-layout'>,</span> <span class='hs-varid'>unmappedWindowRect</span>     <span class='hs-keyglyph'>=</span> <span class='hs-conid'>[]</span>
<a name="line-326"></a>                                               <span class='hs-layout'>}</span>
<a name="line-327"></a>
<a name="line-328"></a><a name="switchLayer"></a><span class='hs-comment'>-- | Switches focus to the closest window in the other layer (floating if the</span>
<a name="line-329"></a><span class='hs-comment'>-- current window is tiled, tiled if the current window is floating).  Closest</span>
<a name="line-330"></a><span class='hs-comment'>-- means that the L1-distance between the centers of the windows is minimized.</span>
<a name="line-331"></a><span class='hs-definition'>switchLayer</span> <span class='hs-keyglyph'>::</span> <span class='hs-conid'>X</span> <span class='hs-conid'>()</span>
<a name="line-332"></a><span class='hs-definition'>switchLayer</span> <span class='hs-keyglyph'>=</span> <span class='hs-varid'>actOnLayer</span> <span class='hs-varid'>otherLayer</span>
<a name="line-333"></a>                         <span class='hs-layout'>(</span> <span class='hs-keyglyph'>\</span> <span class='hs-keyword'>_</span> <span class='hs-varid'>cur</span> <span class='hs-varid'>wins</span> <span class='hs-keyglyph'>-&gt;</span> <span class='hs-varid'>windows</span>
<a name="line-334"></a>                           <span class='hs-varop'>$</span> <span class='hs-varid'>doFocusClosestWindow</span> <span class='hs-varid'>cur</span> <span class='hs-varid'>wins</span>
<a name="line-335"></a>                         <span class='hs-layout'>)</span>
<a name="line-336"></a>                         <span class='hs-layout'>(</span> <span class='hs-keyglyph'>\</span> <span class='hs-keyword'>_</span> <span class='hs-varid'>cur</span> <span class='hs-varid'>wins</span> <span class='hs-keyglyph'>-&gt;</span> <span class='hs-varid'>windows</span>
<a name="line-337"></a>                           <span class='hs-varop'>$</span> <span class='hs-varid'>doFocusClosestWindow</span> <span class='hs-varid'>cur</span> <span class='hs-varid'>wins</span>
<a name="line-338"></a>                         <span class='hs-layout'>)</span>
<a name="line-339"></a>                         <span class='hs-layout'>(</span> <span class='hs-keyglyph'>\</span> <span class='hs-keyword'>_</span> <span class='hs-keyword'>_</span> <span class='hs-keyword'>_</span> <span class='hs-keyglyph'>-&gt;</span> <span class='hs-varid'>return</span> <span class='hs-conid'>()</span> <span class='hs-layout'>)</span>
<a name="line-340"></a>                         <span class='hs-conid'>False</span>
<a name="line-341"></a>
<a name="line-342"></a><a name="windowGo"></a><span class='hs-comment'>-- | Moves the focus to the next window in the given direction and in the same</span>
<a name="line-343"></a><span class='hs-comment'>-- layer as the current window.  The second argument indicates whether</span>
<a name="line-344"></a><span class='hs-comment'>-- navigation should wrap around (e.g., from the left edge of the leftmost</span>
<a name="line-345"></a><span class='hs-comment'>-- screen to the right edge of the rightmost screen).</span>
<a name="line-346"></a><span class='hs-definition'>windowGo</span> <span class='hs-keyglyph'>::</span> <span class='hs-conid'>Direction2D</span> <span class='hs-keyglyph'>-&gt;</span> <span class='hs-conid'>Bool</span> <span class='hs-keyglyph'>-&gt;</span> <span class='hs-conid'>X</span> <span class='hs-conid'>()</span>
<a name="line-347"></a><span class='hs-definition'>windowGo</span> <span class='hs-varid'>dir</span> <span class='hs-varid'>wrap</span> <span class='hs-keyglyph'>=</span> <span class='hs-varid'>actOnLayer</span> <span class='hs-varid'>thisLayer</span>
<a name="line-348"></a>                               <span class='hs-layout'>(</span> <span class='hs-keyglyph'>\</span> <span class='hs-varid'>conf</span> <span class='hs-varid'>cur</span> <span class='hs-varid'>wins</span> <span class='hs-keyglyph'>-&gt;</span> <span class='hs-varid'>windows</span>
<a name="line-349"></a>                                 <span class='hs-varop'>$</span> <span class='hs-varid'>doTiledNavigation</span> <span class='hs-varid'>conf</span> <span class='hs-varid'>dir</span> <span class='hs-conid'>W</span><span class='hs-varop'>.</span><span class='hs-varid'>focusWindow</span> <span class='hs-varid'>cur</span> <span class='hs-varid'>wins</span>
<a name="line-350"></a>                               <span class='hs-layout'>)</span>
<a name="line-351"></a>                               <span class='hs-layout'>(</span> <span class='hs-keyglyph'>\</span> <span class='hs-varid'>conf</span> <span class='hs-varid'>cur</span> <span class='hs-varid'>wins</span> <span class='hs-keyglyph'>-&gt;</span> <span class='hs-varid'>windows</span>
<a name="line-352"></a>                                 <span class='hs-varop'>$</span> <span class='hs-varid'>doFloatNavigation</span> <span class='hs-varid'>conf</span> <span class='hs-varid'>dir</span> <span class='hs-conid'>W</span><span class='hs-varop'>.</span><span class='hs-varid'>focusWindow</span> <span class='hs-varid'>cur</span> <span class='hs-varid'>wins</span>
<a name="line-353"></a>                               <span class='hs-layout'>)</span>
<a name="line-354"></a>                               <span class='hs-layout'>(</span> <span class='hs-keyglyph'>\</span> <span class='hs-varid'>conf</span> <span class='hs-varid'>cur</span> <span class='hs-varid'>wspcs</span> <span class='hs-keyglyph'>-&gt;</span> <span class='hs-varid'>windows</span>
<a name="line-355"></a>                                 <span class='hs-varop'>$</span> <span class='hs-varid'>doScreenNavigation</span> <span class='hs-varid'>conf</span> <span class='hs-varid'>dir</span> <span class='hs-conid'>W</span><span class='hs-varop'>.</span><span class='hs-varid'>view</span> <span class='hs-varid'>cur</span> <span class='hs-varid'>wspcs</span>
<a name="line-356"></a>                               <span class='hs-layout'>)</span>
<a name="line-357"></a>                               <span class='hs-varid'>wrap</span>
<a name="line-358"></a>
<a name="line-359"></a><a name="windowSwap"></a><span class='hs-comment'>-- | Swaps the current window with the next window in the given direction and in</span>
<a name="line-360"></a><span class='hs-comment'>-- the same layer as the current window.  (In the floating layer, all that</span>
<a name="line-361"></a><span class='hs-comment'>-- changes for the two windows is their stacking order if they're on the same</span>
<a name="line-362"></a><span class='hs-comment'>-- screen.  If they're on different screens, each window is moved to the other</span>
<a name="line-363"></a><span class='hs-comment'>-- window's screen but retains its position and size relative to the screen.)</span>
<a name="line-364"></a><span class='hs-comment'>-- The second argument indicates wrapping (see 'windowGo').</span>
<a name="line-365"></a><span class='hs-definition'>windowSwap</span> <span class='hs-keyglyph'>::</span> <span class='hs-conid'>Direction2D</span> <span class='hs-keyglyph'>-&gt;</span> <span class='hs-conid'>Bool</span> <span class='hs-keyglyph'>-&gt;</span> <span class='hs-conid'>X</span> <span class='hs-conid'>()</span>
<a name="line-366"></a><span class='hs-definition'>windowSwap</span> <span class='hs-varid'>dir</span> <span class='hs-varid'>wrap</span> <span class='hs-keyglyph'>=</span> <span class='hs-varid'>actOnLayer</span> <span class='hs-varid'>thisLayer</span>
<a name="line-367"></a>                                 <span class='hs-layout'>(</span> <span class='hs-keyglyph'>\</span> <span class='hs-varid'>conf</span> <span class='hs-varid'>cur</span> <span class='hs-varid'>wins</span> <span class='hs-keyglyph'>-&gt;</span> <span class='hs-varid'>windows</span>
<a name="line-368"></a>                                   <span class='hs-varop'>$</span> <span class='hs-varid'>doTiledNavigation</span> <span class='hs-varid'>conf</span> <span class='hs-varid'>dir</span> <span class='hs-varid'>swap</span> <span class='hs-varid'>cur</span> <span class='hs-varid'>wins</span>
<a name="line-369"></a>                                 <span class='hs-layout'>)</span>
<a name="line-370"></a>                                 <span class='hs-layout'>(</span> <span class='hs-keyglyph'>\</span> <span class='hs-varid'>conf</span> <span class='hs-varid'>cur</span> <span class='hs-varid'>wins</span> <span class='hs-keyglyph'>-&gt;</span> <span class='hs-varid'>windows</span>
<a name="line-371"></a>                                   <span class='hs-varop'>$</span> <span class='hs-varid'>doFloatNavigation</span> <span class='hs-varid'>conf</span> <span class='hs-varid'>dir</span> <span class='hs-varid'>swap</span> <span class='hs-varid'>cur</span> <span class='hs-varid'>wins</span>
<a name="line-372"></a>                                 <span class='hs-layout'>)</span>
<a name="line-373"></a>                                 <span class='hs-layout'>(</span> <span class='hs-keyglyph'>\</span> <span class='hs-keyword'>_</span> <span class='hs-keyword'>_</span> <span class='hs-keyword'>_</span> <span class='hs-keyglyph'>-&gt;</span> <span class='hs-varid'>return</span> <span class='hs-conid'>()</span> <span class='hs-layout'>)</span>
<a name="line-374"></a>                                 <span class='hs-varid'>wrap</span>
<a name="line-375"></a>
<a name="line-376"></a><a name="windowToScreen"></a><span class='hs-comment'>-- | Moves the current window to the next screen in the given direction.  The</span>
<a name="line-377"></a><span class='hs-comment'>-- second argument indicates wrapping (see 'windowGo').</span>
<a name="line-378"></a><span class='hs-definition'>windowToScreen</span> <span class='hs-keyglyph'>::</span> <span class='hs-conid'>Direction2D</span> <span class='hs-keyglyph'>-&gt;</span> <span class='hs-conid'>Bool</span> <span class='hs-keyglyph'>-&gt;</span> <span class='hs-conid'>X</span> <span class='hs-conid'>()</span>
<a name="line-379"></a><span class='hs-definition'>windowToScreen</span> <span class='hs-varid'>dir</span> <span class='hs-varid'>wrap</span> <span class='hs-keyglyph'>=</span> <span class='hs-varid'>actOnScreens</span> <span class='hs-layout'>(</span> <span class='hs-keyglyph'>\</span> <span class='hs-varid'>conf</span> <span class='hs-varid'>cur</span> <span class='hs-varid'>wspcs</span> <span class='hs-keyglyph'>-&gt;</span> <span class='hs-varid'>windows</span>
<a name="line-380"></a>                                         <span class='hs-varop'>$</span> <span class='hs-varid'>doScreenNavigation</span> <span class='hs-varid'>conf</span> <span class='hs-varid'>dir</span> <span class='hs-conid'>W</span><span class='hs-varop'>.</span><span class='hs-varid'>shift</span> <span class='hs-varid'>cur</span> <span class='hs-varid'>wspcs</span>
<a name="line-381"></a>                                       <span class='hs-layout'>)</span>
<a name="line-382"></a>                                       <span class='hs-varid'>wrap</span>
<a name="line-383"></a>
<a name="line-384"></a><a name="screenGo"></a><span class='hs-comment'>-- | Moves the focus to the next screen in the given direction.  The second</span>
<a name="line-385"></a><span class='hs-comment'>-- argument indicates wrapping (see 'windowGo').</span>
<a name="line-386"></a><span class='hs-definition'>screenGo</span> <span class='hs-keyglyph'>::</span> <span class='hs-conid'>Direction2D</span> <span class='hs-keyglyph'>-&gt;</span> <span class='hs-conid'>Bool</span> <span class='hs-keyglyph'>-&gt;</span> <span class='hs-conid'>X</span> <span class='hs-conid'>()</span>
<a name="line-387"></a><span class='hs-definition'>screenGo</span> <span class='hs-varid'>dir</span> <span class='hs-varid'>wrap</span> <span class='hs-keyglyph'>=</span> <span class='hs-varid'>actOnScreens</span> <span class='hs-layout'>(</span> <span class='hs-keyglyph'>\</span> <span class='hs-varid'>conf</span> <span class='hs-varid'>cur</span> <span class='hs-varid'>wspcs</span> <span class='hs-keyglyph'>-&gt;</span> <span class='hs-varid'>windows</span>
<a name="line-388"></a>                                   <span class='hs-varop'>$</span> <span class='hs-varid'>doScreenNavigation</span> <span class='hs-varid'>conf</span> <span class='hs-varid'>dir</span> <span class='hs-conid'>W</span><span class='hs-varop'>.</span><span class='hs-varid'>view</span> <span class='hs-varid'>cur</span> <span class='hs-varid'>wspcs</span>
<a name="line-389"></a>                                 <span class='hs-layout'>)</span>
<a name="line-390"></a>                                 <span class='hs-varid'>wrap</span>
<a name="line-391"></a>
<a name="line-392"></a><a name="screenSwap"></a><span class='hs-comment'>-- | Swaps the workspace on the current screen with the workspace on the screen</span>
<a name="line-393"></a><span class='hs-comment'>-- in the given direction.  The second argument indicates wrapping (see</span>
<a name="line-394"></a><span class='hs-comment'>-- 'windowGo').</span>
<a name="line-395"></a><span class='hs-definition'>screenSwap</span> <span class='hs-keyglyph'>::</span> <span class='hs-conid'>Direction2D</span> <span class='hs-keyglyph'>-&gt;</span> <span class='hs-conid'>Bool</span> <span class='hs-keyglyph'>-&gt;</span> <span class='hs-conid'>X</span> <span class='hs-conid'>()</span>
<a name="line-396"></a><span class='hs-definition'>screenSwap</span> <span class='hs-varid'>dir</span> <span class='hs-varid'>wrap</span> <span class='hs-keyglyph'>=</span> <span class='hs-varid'>actOnScreens</span> <span class='hs-layout'>(</span> <span class='hs-keyglyph'>\</span> <span class='hs-varid'>conf</span> <span class='hs-varid'>cur</span> <span class='hs-varid'>wspcs</span> <span class='hs-keyglyph'>-&gt;</span> <span class='hs-varid'>windows</span>
<a name="line-397"></a>                                     <span class='hs-varop'>$</span> <span class='hs-varid'>doScreenNavigation</span> <span class='hs-varid'>conf</span> <span class='hs-varid'>dir</span> <span class='hs-conid'>W</span><span class='hs-varop'>.</span><span class='hs-varid'>greedyView</span> <span class='hs-varid'>cur</span> <span class='hs-varid'>wspcs</span>
<a name="line-398"></a>                                   <span class='hs-layout'>)</span>
<a name="line-399"></a>                                   <span class='hs-varid'>wrap</span>
<a name="line-400"></a>
<a name="line-401"></a><a name="fullScreenRect"></a><span class='hs-comment'>-- | Maps each window to a fullscreen rect.  This may not be the same rectangle the</span>
<a name="line-402"></a><span class='hs-comment'>-- window maps to under the Full layout or a similar layout if the layout</span>
<a name="line-403"></a><span class='hs-comment'>-- respects statusbar struts.  In such cases, it may be better to use</span>
<a name="line-404"></a><span class='hs-comment'>-- 'singleWindowRect'.</span>
<a name="line-405"></a><span class='hs-definition'>fullScreenRect</span> <span class='hs-keyglyph'>::</span> <span class='hs-conid'>Screen</span> <span class='hs-keyglyph'>-&gt;</span> <span class='hs-conid'>Window</span> <span class='hs-keyglyph'>-&gt;</span> <span class='hs-conid'>X</span> <span class='hs-layout'>(</span><span class='hs-conid'>Maybe</span> <span class='hs-conid'>Rectangle</span><span class='hs-layout'>)</span>
<a name="line-406"></a><span class='hs-definition'>fullScreenRect</span> <span class='hs-varid'>scr</span> <span class='hs-keyword'>_</span> <span class='hs-keyglyph'>=</span> <span class='hs-varid'>return</span> <span class='hs-layout'>(</span><span class='hs-conid'>Just</span> <span class='hs-varop'>.</span> <span class='hs-varid'>screenRect</span> <span class='hs-varop'>.</span> <span class='hs-conid'>W</span><span class='hs-varop'>.</span><span class='hs-varid'>screenDetail</span> <span class='hs-varop'>$</span> <span class='hs-varid'>scr</span><span class='hs-layout'>)</span>
<a name="line-407"></a>
<a name="line-408"></a><a name="singleWindowRect"></a><span class='hs-comment'>-- | Maps each window to the rectangle it would receive if it was the only</span>
<a name="line-409"></a><span class='hs-comment'>-- window in the layout.  Useful, for example, for determining the default</span>
<a name="line-410"></a><span class='hs-comment'>-- rectangle for unmapped windows in a Full layout that respects statusbar</span>
<a name="line-411"></a><span class='hs-comment'>-- struts.</span>
<a name="line-412"></a><span class='hs-definition'>singleWindowRect</span> <span class='hs-keyglyph'>::</span> <span class='hs-conid'>Screen</span> <span class='hs-keyglyph'>-&gt;</span> <span class='hs-conid'>Window</span> <span class='hs-keyglyph'>-&gt;</span> <span class='hs-conid'>X</span> <span class='hs-layout'>(</span><span class='hs-conid'>Maybe</span> <span class='hs-conid'>Rectangle</span><span class='hs-layout'>)</span>
<a name="line-413"></a><span class='hs-definition'>singleWindowRect</span> <span class='hs-varid'>scr</span> <span class='hs-varid'>win</span>  <span class='hs-keyglyph'>=</span>  <span class='hs-varid'>listToMaybe</span>
<a name="line-414"></a>                          <span class='hs-varop'>.</span>  <span class='hs-varid'>map</span> <span class='hs-varid'>snd</span>
<a name="line-415"></a>                          <span class='hs-varop'>.</span>  <span class='hs-varid'>fst</span>
<a name="line-416"></a>                         <span class='hs-varop'>&lt;$&gt;</span> <span class='hs-varid'>runLayout</span> <span class='hs-layout'>(</span><span class='hs-layout'>(</span><span class='hs-conid'>W</span><span class='hs-varop'>.</span><span class='hs-varid'>workspace</span> <span class='hs-varid'>scr</span><span class='hs-layout'>)</span> <span class='hs-layout'>{</span> <span class='hs-conid'>W</span><span class='hs-varop'>.</span><span class='hs-varid'>stack</span> <span class='hs-keyglyph'>=</span> <span class='hs-conid'>W</span><span class='hs-varop'>.</span><span class='hs-varid'>differentiate</span> <span class='hs-keyglyph'>[</span><span class='hs-varid'>win</span><span class='hs-keyglyph'>]</span> <span class='hs-layout'>}</span><span class='hs-layout'>)</span>
<a name="line-417"></a>                                       <span class='hs-layout'>(</span><span class='hs-varid'>screenRect</span> <span class='hs-varop'>.</span> <span class='hs-conid'>W</span><span class='hs-varop'>.</span><span class='hs-varid'>screenDetail</span> <span class='hs-varop'>$</span> <span class='hs-varid'>scr</span><span class='hs-layout'>)</span>
<a name="line-418"></a>
<a name="line-419"></a><span class='hs-comment'>----------------------------------------------------------------------------------------------------</span>
<a name="line-420"></a><span class='hs-comment'>----------------------------------------------------------------------------------------------------</span>
<a name="line-421"></a><span class='hs-comment'>--                                                                                                --</span>
<a name="line-422"></a><span class='hs-comment'>--                                       PRIVATE X ACTIONS                                        --</span>
<a name="line-423"></a><span class='hs-comment'>--                                                                                                --</span>
<a name="line-424"></a><span class='hs-comment'>----------------------------------------------------------------------------------------------------</span>
<a name="line-425"></a><span class='hs-comment'>----------------------------------------------------------------------------------------------------</span>
<a name="line-426"></a>
<a name="line-427"></a><a name="actOnLayer"></a><span class='hs-comment'>-- | Acts on the appropriate layer using the given action functions</span>
<a name="line-428"></a><span class='hs-definition'>actOnLayer</span> <span class='hs-keyglyph'>::</span> <span class='hs-layout'>(</span><span class='hs-keyglyph'>[</span><span class='hs-conid'>WinRect</span><span class='hs-keyglyph'>]</span> <span class='hs-keyglyph'>-&gt;</span> <span class='hs-keyglyph'>[</span><span class='hs-conid'>WinRect</span><span class='hs-keyglyph'>]</span> <span class='hs-keyglyph'>-&gt;</span> <span class='hs-keyglyph'>[</span><span class='hs-conid'>WinRect</span><span class='hs-keyglyph'>]</span><span class='hs-layout'>)</span>                <span class='hs-comment'>-- ^ Chooses which layer to operate on, relative</span>
<a name="line-429"></a>                                                                   <span class='hs-comment'>-- to the current window (same or other layer)</span>
<a name="line-430"></a>           <span class='hs-keyglyph'>-&gt;</span> <span class='hs-layout'>(</span><span class='hs-conid'>Navigation2DConfig</span> <span class='hs-keyglyph'>-&gt;</span> <span class='hs-conid'>WinRect</span> <span class='hs-keyglyph'>-&gt;</span> <span class='hs-keyglyph'>[</span><span class='hs-conid'>WinRect</span><span class='hs-keyglyph'>]</span> <span class='hs-keyglyph'>-&gt;</span> <span class='hs-conid'>X</span> <span class='hs-conid'>()</span><span class='hs-layout'>)</span> <span class='hs-comment'>-- ^ The action for the tiled layer</span>
<a name="line-431"></a>           <span class='hs-keyglyph'>-&gt;</span> <span class='hs-layout'>(</span><span class='hs-conid'>Navigation2DConfig</span> <span class='hs-keyglyph'>-&gt;</span> <span class='hs-conid'>WinRect</span> <span class='hs-keyglyph'>-&gt;</span> <span class='hs-keyglyph'>[</span><span class='hs-conid'>WinRect</span><span class='hs-keyglyph'>]</span> <span class='hs-keyglyph'>-&gt;</span> <span class='hs-conid'>X</span> <span class='hs-conid'>()</span><span class='hs-layout'>)</span> <span class='hs-comment'>-- ^ The action for the float layer</span>
<a name="line-432"></a>           <span class='hs-keyglyph'>-&gt;</span> <span class='hs-layout'>(</span><span class='hs-conid'>Navigation2DConfig</span> <span class='hs-keyglyph'>-&gt;</span> <span class='hs-conid'>WSRect</span>  <span class='hs-keyglyph'>-&gt;</span> <span class='hs-keyglyph'>[</span><span class='hs-conid'>WSRect</span><span class='hs-keyglyph'>]</span>  <span class='hs-keyglyph'>-&gt;</span> <span class='hs-conid'>X</span> <span class='hs-conid'>()</span><span class='hs-layout'>)</span> <span class='hs-comment'>-- ^ The action if the current workspace is empty</span>
<a name="line-433"></a>           <span class='hs-keyglyph'>-&gt;</span> <span class='hs-conid'>Bool</span>                                                 <span class='hs-comment'>-- ^ Should navigation wrap around screen edges?</span>
<a name="line-434"></a>           <span class='hs-keyglyph'>-&gt;</span> <span class='hs-conid'>X</span> <span class='hs-conid'>()</span>
<a name="line-435"></a><span class='hs-definition'>actOnLayer</span> <span class='hs-varid'>choice</span> <span class='hs-varid'>tiledact</span> <span class='hs-varid'>floatact</span> <span class='hs-varid'>wsact</span> <span class='hs-varid'>wrap</span> <span class='hs-keyglyph'>=</span> <span class='hs-varid'>withWindowSet</span> <span class='hs-varop'>$</span> <span class='hs-keyglyph'>\</span><span class='hs-varid'>winset</span> <span class='hs-keyglyph'>-&gt;</span> <span class='hs-keyword'>do</span>
<a name="line-436"></a>  <span class='hs-varid'>conf</span> <span class='hs-keyglyph'>&lt;-</span> <span class='hs-conid'>XS</span><span class='hs-varop'>.</span><span class='hs-varid'>get</span>
<a name="line-437"></a>  <span class='hs-layout'>(</span><span class='hs-varid'>floating</span><span class='hs-layout'>,</span> <span class='hs-varid'>tiled</span><span class='hs-layout'>)</span> <span class='hs-keyglyph'>&lt;-</span> <span class='hs-varid'>navigableWindows</span> <span class='hs-varid'>conf</span> <span class='hs-varid'>wrap</span> <span class='hs-varid'>winset</span>
<a name="line-438"></a>  <span class='hs-keyword'>let</span> <span class='hs-varid'>cur</span> <span class='hs-keyglyph'>=</span> <span class='hs-conid'>W</span><span class='hs-varop'>.</span><span class='hs-varid'>peek</span> <span class='hs-varid'>winset</span>
<a name="line-439"></a>  <span class='hs-keyword'>case</span> <span class='hs-varid'>cur</span> <span class='hs-keyword'>of</span>
<a name="line-440"></a>    <span class='hs-conid'>Nothing</span>                                   <span class='hs-keyglyph'>-&gt;</span> <span class='hs-varid'>actOnScreens</span> <span class='hs-varid'>wsact</span> <span class='hs-varid'>wrap</span>
<a name="line-441"></a>    <span class='hs-conid'>Just</span> <span class='hs-varid'>w</span> <span class='hs-keyglyph'>|</span> <span class='hs-conid'>Just</span> <span class='hs-varid'>rect</span> <span class='hs-keyglyph'>&lt;-</span> <span class='hs-conid'>L</span><span class='hs-varop'>.</span><span class='hs-varid'>lookup</span> <span class='hs-varid'>w</span> <span class='hs-varid'>tiled</span>    <span class='hs-keyglyph'>-&gt;</span> <span class='hs-varid'>tiledact</span> <span class='hs-varid'>conf</span> <span class='hs-layout'>(</span><span class='hs-varid'>w</span><span class='hs-layout'>,</span> <span class='hs-varid'>rect</span><span class='hs-layout'>)</span> <span class='hs-layout'>(</span><span class='hs-varid'>choice</span> <span class='hs-varid'>tiled</span> <span class='hs-varid'>floating</span><span class='hs-layout'>)</span>
<a name="line-442"></a>           <span class='hs-keyglyph'>|</span> <span class='hs-conid'>Just</span> <span class='hs-varid'>rect</span> <span class='hs-keyglyph'>&lt;-</span> <span class='hs-conid'>L</span><span class='hs-varop'>.</span><span class='hs-varid'>lookup</span> <span class='hs-varid'>w</span> <span class='hs-varid'>floating</span> <span class='hs-keyglyph'>-&gt;</span> <span class='hs-varid'>floatact</span> <span class='hs-varid'>conf</span> <span class='hs-layout'>(</span><span class='hs-varid'>w</span><span class='hs-layout'>,</span> <span class='hs-varid'>rect</span><span class='hs-layout'>)</span> <span class='hs-layout'>(</span><span class='hs-varid'>choice</span> <span class='hs-varid'>floating</span> <span class='hs-varid'>tiled</span><span class='hs-layout'>)</span>
<a name="line-443"></a>           <span class='hs-keyglyph'>|</span> <span class='hs-varid'>otherwise</span>                        <span class='hs-keyglyph'>-&gt;</span> <span class='hs-varid'>return</span> <span class='hs-conid'>()</span>
<a name="line-444"></a>
<a name="line-445"></a><a name="navigableWindows"></a><span class='hs-comment'>-- | Returns the list of windows on the currently visible workspaces</span>
<a name="line-446"></a><span class='hs-definition'>navigableWindows</span> <span class='hs-keyglyph'>::</span> <span class='hs-conid'>Navigation2DConfig</span> <span class='hs-keyglyph'>-&gt;</span> <span class='hs-conid'>Bool</span> <span class='hs-keyglyph'>-&gt;</span> <span class='hs-conid'>WindowSet</span> <span class='hs-keyglyph'>-&gt;</span> <span class='hs-conid'>X</span> <span class='hs-layout'>(</span><span class='hs-keyglyph'>[</span><span class='hs-conid'>WinRect</span><span class='hs-keyglyph'>]</span><span class='hs-layout'>,</span> <span class='hs-keyglyph'>[</span><span class='hs-conid'>WinRect</span><span class='hs-keyglyph'>]</span><span class='hs-layout'>)</span>
<a name="line-447"></a><span class='hs-definition'>navigableWindows</span> <span class='hs-varid'>conf</span> <span class='hs-varid'>wrap</span> <span class='hs-varid'>winset</span>  <span class='hs-keyglyph'>=</span>  <span class='hs-conid'>L</span><span class='hs-varop'>.</span><span class='hs-varid'>partition</span> <span class='hs-layout'>(</span><span class='hs-keyglyph'>\</span><span class='hs-layout'>(</span><span class='hs-varid'>win</span><span class='hs-layout'>,</span> <span class='hs-keyword'>_</span><span class='hs-layout'>)</span> <span class='hs-keyglyph'>-&gt;</span> <span class='hs-conid'>M</span><span class='hs-varop'>.</span><span class='hs-varid'>member</span> <span class='hs-varid'>win</span> <span class='hs-layout'>(</span><span class='hs-conid'>W</span><span class='hs-varop'>.</span><span class='hs-varid'>floating</span> <span class='hs-varid'>winset</span><span class='hs-layout'>)</span><span class='hs-layout'>)</span>
<a name="line-448"></a>                                   <span class='hs-varop'>.</span>  <span class='hs-varid'>addWrapping</span> <span class='hs-varid'>winset</span> <span class='hs-varid'>wrap</span>
<a name="line-449"></a>                                   <span class='hs-varop'>.</span>  <span class='hs-varid'>catMaybes</span>
<a name="line-450"></a>                                   <span class='hs-varop'>.</span>  <span class='hs-varid'>concat</span>
<a name="line-451"></a>                                  <span class='hs-varop'>&lt;$&gt;</span>
<a name="line-452"></a>                                   <span class='hs-layout'>(</span>  <span class='hs-varid'>mapM</span> <span class='hs-layout'>(</span> <span class='hs-keyglyph'>\</span><span class='hs-varid'>scr</span> <span class='hs-keyglyph'>-&gt;</span> <span class='hs-varid'>mapM</span> <span class='hs-layout'>(</span><span class='hs-varid'>maybeWinRect</span> <span class='hs-varid'>scr</span><span class='hs-layout'>)</span>
<a name="line-453"></a>                                                   <span class='hs-varop'>$</span> <span class='hs-conid'>W</span><span class='hs-varop'>.</span><span class='hs-varid'>integrate'</span>
<a name="line-454"></a>                                                   <span class='hs-varop'>$</span> <span class='hs-conid'>W</span><span class='hs-varop'>.</span><span class='hs-varid'>stack</span>
<a name="line-455"></a>                                                   <span class='hs-varop'>$</span> <span class='hs-conid'>W</span><span class='hs-varop'>.</span><span class='hs-varid'>workspace</span> <span class='hs-varid'>scr</span>
<a name="line-456"></a>                                           <span class='hs-layout'>)</span>
<a name="line-457"></a>                                   <span class='hs-varop'>.</span>  <span class='hs-varid'>sortedScreens</span>
<a name="line-458"></a>                                   <span class='hs-layout'>)</span>  <span class='hs-varid'>winset</span>
<a name="line-459"></a>  <span class='hs-keyword'>where</span>
<a name="line-460"></a>    <span class='hs-varid'>maybeWinRect</span> <span class='hs-varid'>scr</span> <span class='hs-varid'>win</span> <span class='hs-keyglyph'>=</span> <span class='hs-keyword'>do</span>
<a name="line-461"></a>      <span class='hs-varid'>winrect</span> <span class='hs-keyglyph'>&lt;-</span> <span class='hs-varid'>windowRect</span> <span class='hs-varid'>win</span>
<a name="line-462"></a>      <span class='hs-varid'>rect</span> <span class='hs-keyglyph'>&lt;-</span> <span class='hs-keyword'>case</span> <span class='hs-varid'>winrect</span> <span class='hs-keyword'>of</span>
<a name="line-463"></a>                <span class='hs-conid'>Just</span> <span class='hs-keyword'>_</span>  <span class='hs-keyglyph'>-&gt;</span> <span class='hs-varid'>return</span> <span class='hs-varid'>winrect</span>
<a name="line-464"></a>                <span class='hs-conid'>Nothing</span> <span class='hs-keyglyph'>-&gt;</span> <span class='hs-varid'>maybe</span> <span class='hs-layout'>(</span><span class='hs-varid'>return</span> <span class='hs-conid'>Nothing</span><span class='hs-layout'>)</span>
<a name="line-465"></a>                                 <span class='hs-layout'>(</span><span class='hs-keyglyph'>\</span><span class='hs-varid'>f</span> <span class='hs-keyglyph'>-&gt;</span> <span class='hs-varid'>f</span> <span class='hs-varid'>scr</span> <span class='hs-varid'>win</span><span class='hs-layout'>)</span>
<a name="line-466"></a>                                 <span class='hs-layout'>(</span><span class='hs-conid'>L</span><span class='hs-varop'>.</span><span class='hs-varid'>lookup</span> <span class='hs-layout'>(</span><span class='hs-varid'>description</span> <span class='hs-varop'>.</span> <span class='hs-conid'>W</span><span class='hs-varop'>.</span><span class='hs-varid'>layout</span> <span class='hs-varop'>.</span> <span class='hs-conid'>W</span><span class='hs-varop'>.</span><span class='hs-varid'>workspace</span> <span class='hs-varop'>$</span> <span class='hs-varid'>scr</span><span class='hs-layout'>)</span> <span class='hs-layout'>(</span><span class='hs-varid'>unmappedWindowRect</span> <span class='hs-varid'>conf</span><span class='hs-layout'>)</span><span class='hs-layout'>)</span>
<a name="line-467"></a>      <span class='hs-varid'>return</span> <span class='hs-layout'>(</span><span class='hs-conid'>(,)</span> <span class='hs-varid'>win</span> <span class='hs-varop'>&lt;$&gt;</span> <span class='hs-varid'>rect</span><span class='hs-layout'>)</span>
<a name="line-468"></a>
<a name="line-469"></a><a name="windowRect"></a><span class='hs-comment'>-- | Returns the current rectangle of the given window, Nothing if the window isn't mapped</span>
<a name="line-470"></a><span class='hs-definition'>windowRect</span> <span class='hs-keyglyph'>::</span> <span class='hs-conid'>Window</span> <span class='hs-keyglyph'>-&gt;</span> <span class='hs-conid'>X</span> <span class='hs-layout'>(</span><span class='hs-conid'>Maybe</span> <span class='hs-conid'>Rectangle</span><span class='hs-layout'>)</span>
<a name="line-471"></a><span class='hs-definition'>windowRect</span> <span class='hs-varid'>win</span> <span class='hs-keyglyph'>=</span> <span class='hs-varid'>withDisplay</span> <span class='hs-varop'>$</span> <span class='hs-keyglyph'>\</span><span class='hs-varid'>dpy</span> <span class='hs-keyglyph'>-&gt;</span> <span class='hs-keyword'>do</span>
<a name="line-472"></a>  <span class='hs-varid'>mp</span> <span class='hs-keyglyph'>&lt;-</span> <span class='hs-varid'>isMapped</span> <span class='hs-varid'>win</span>
<a name="line-473"></a>  <span class='hs-keyword'>if</span> <span class='hs-varid'>mp</span> <span class='hs-keyword'>then</span> <span class='hs-keyword'>do</span> <span class='hs-layout'>(</span><span class='hs-keyword'>_</span><span class='hs-layout'>,</span> <span class='hs-varid'>x</span><span class='hs-layout'>,</span> <span class='hs-varid'>y</span><span class='hs-layout'>,</span> <span class='hs-varid'>w</span><span class='hs-layout'>,</span> <span class='hs-varid'>h</span><span class='hs-layout'>,</span> <span class='hs-varid'>bw</span><span class='hs-layout'>,</span> <span class='hs-keyword'>_</span><span class='hs-layout'>)</span> <span class='hs-keyglyph'>&lt;-</span> <span class='hs-varid'>io</span> <span class='hs-varop'>$</span> <span class='hs-varid'>getGeometry</span> <span class='hs-varid'>dpy</span> <span class='hs-varid'>win</span>
<a name="line-474"></a>                <span class='hs-varid'>return</span> <span class='hs-varop'>$</span> <span class='hs-conid'>Just</span> <span class='hs-varop'>$</span> <span class='hs-conid'>Rectangle</span> <span class='hs-varid'>x</span> <span class='hs-varid'>y</span> <span class='hs-layout'>(</span><span class='hs-varid'>w</span> <span class='hs-varop'>+</span> <span class='hs-num'>2</span> <span class='hs-varop'>*</span> <span class='hs-varid'>bw</span><span class='hs-layout'>)</span> <span class='hs-layout'>(</span><span class='hs-varid'>h</span> <span class='hs-varop'>+</span> <span class='hs-num'>2</span> <span class='hs-varop'>*</span> <span class='hs-varid'>bw</span><span class='hs-layout'>)</span>
<a name="line-475"></a>                <span class='hs-varop'>`catchX`</span> <span class='hs-varid'>return</span> <span class='hs-conid'>Nothing</span>
<a name="line-476"></a>        <span class='hs-keyword'>else</span> <span class='hs-varid'>return</span> <span class='hs-conid'>Nothing</span>
<a name="line-477"></a>
<a name="line-478"></a><a name="actOnScreens"></a><span class='hs-comment'>-- | Acts on the screens using the given action function</span>
<a name="line-479"></a><span class='hs-definition'>actOnScreens</span> <span class='hs-keyglyph'>::</span> <span class='hs-layout'>(</span><span class='hs-conid'>Navigation2DConfig</span> <span class='hs-keyglyph'>-&gt;</span> <span class='hs-conid'>WSRect</span> <span class='hs-keyglyph'>-&gt;</span> <span class='hs-keyglyph'>[</span><span class='hs-conid'>WSRect</span><span class='hs-keyglyph'>]</span> <span class='hs-keyglyph'>-&gt;</span> <span class='hs-conid'>X</span> <span class='hs-conid'>()</span><span class='hs-layout'>)</span>
<a name="line-480"></a>             <span class='hs-keyglyph'>-&gt;</span> <span class='hs-conid'>Bool</span>  <span class='hs-comment'>-- ^ Should wrapping be used?</span>
<a name="line-481"></a>             <span class='hs-keyglyph'>-&gt;</span> <span class='hs-conid'>X</span> <span class='hs-conid'>()</span>
<a name="line-482"></a><span class='hs-definition'>actOnScreens</span> <span class='hs-varid'>act</span> <span class='hs-varid'>wrap</span> <span class='hs-keyglyph'>=</span> <span class='hs-varid'>withWindowSet</span> <span class='hs-varop'>$</span> <span class='hs-keyglyph'>\</span><span class='hs-varid'>winset</span> <span class='hs-keyglyph'>-&gt;</span> <span class='hs-keyword'>do</span>
<a name="line-483"></a>  <span class='hs-varid'>conf</span> <span class='hs-keyglyph'>&lt;-</span> <span class='hs-conid'>XS</span><span class='hs-varop'>.</span><span class='hs-varid'>get</span>
<a name="line-484"></a>  <span class='hs-keyword'>let</span> <span class='hs-varid'>wsrects</span> <span class='hs-keyglyph'>=</span> <span class='hs-varid'>visibleWorkspaces</span> <span class='hs-varid'>winset</span> <span class='hs-varid'>wrap</span>
<a name="line-485"></a>      <span class='hs-varid'>cur</span>     <span class='hs-keyglyph'>=</span> <span class='hs-conid'>W</span><span class='hs-varop'>.</span><span class='hs-varid'>tag</span> <span class='hs-varop'>.</span> <span class='hs-conid'>W</span><span class='hs-varop'>.</span><span class='hs-varid'>workspace</span> <span class='hs-varop'>.</span> <span class='hs-conid'>W</span><span class='hs-varop'>.</span><span class='hs-varid'>current</span> <span class='hs-varop'>$</span> <span class='hs-varid'>winset</span>
<a name="line-486"></a>      <span class='hs-varid'>rect</span>    <span class='hs-keyglyph'>=</span> <span class='hs-varid'>fromJust</span> <span class='hs-varop'>$</span> <span class='hs-conid'>L</span><span class='hs-varop'>.</span><span class='hs-varid'>lookup</span> <span class='hs-varid'>cur</span> <span class='hs-varid'>wsrects</span>
<a name="line-487"></a>  <span class='hs-varid'>act</span> <span class='hs-varid'>conf</span> <span class='hs-layout'>(</span><span class='hs-varid'>cur</span><span class='hs-layout'>,</span> <span class='hs-varid'>rect</span><span class='hs-layout'>)</span> <span class='hs-varid'>wsrects</span>
<a name="line-488"></a>
<a name="line-489"></a><a name="isMapped"></a><span class='hs-comment'>-- | Determines whether a given window is mapped</span>
<a name="line-490"></a><span class='hs-definition'>isMapped</span> <span class='hs-keyglyph'>::</span> <span class='hs-conid'>Window</span> <span class='hs-keyglyph'>-&gt;</span> <span class='hs-conid'>X</span> <span class='hs-conid'>Bool</span>
<a name="line-491"></a><span class='hs-definition'>isMapped</span> <span class='hs-varid'>win</span>  <span class='hs-keyglyph'>=</span>  <span class='hs-varid'>withDisplay</span>
<a name="line-492"></a>              <span class='hs-varop'>$</span>  <span class='hs-keyglyph'>\</span><span class='hs-varid'>dpy</span> <span class='hs-keyglyph'>-&gt;</span> <span class='hs-varid'>io</span>
<a name="line-493"></a>              <span class='hs-varop'>$</span>  <span class='hs-layout'>(</span><span class='hs-varid'>waIsUnmapped</span> <span class='hs-varop'>/=</span><span class='hs-layout'>)</span>
<a name="line-494"></a>              <span class='hs-varop'>.</span>  <span class='hs-varid'>wa_map_state</span>
<a name="line-495"></a>             <span class='hs-varop'>&lt;$&gt;</span> <span class='hs-varid'>getWindowAttributes</span> <span class='hs-varid'>dpy</span> <span class='hs-varid'>win</span>
<a name="line-496"></a>
<a name="line-497"></a><span class='hs-comment'>----------------------------------------------------------------------------------------------------</span>
<a name="line-498"></a><span class='hs-comment'>----------------------------------------------------------------------------------------------------</span>
<a name="line-499"></a><span class='hs-comment'>--                                                                                                --</span>
<a name="line-500"></a><span class='hs-comment'>--                                     PRIVATE PURE FUNCTIONS                                     --</span>
<a name="line-501"></a><span class='hs-comment'>--                                                                                                --</span>
<a name="line-502"></a><span class='hs-comment'>----------------------------------------------------------------------------------------------------</span>
<a name="line-503"></a><span class='hs-comment'>----------------------------------------------------------------------------------------------------</span>
<a name="line-504"></a>
<a name="line-505"></a><a name="doFocusClosestWindow"></a><span class='hs-comment'>-- | Finds the window closest to the given window and focuses it. Ties are</span>
<a name="line-506"></a><span class='hs-comment'>-- broken by choosing the first window in the window stack among the tied</span>
<a name="line-507"></a><span class='hs-comment'>-- windows.  (The stack order is the one produced by integrate'ing each visible</span>
<a name="line-508"></a><span class='hs-comment'>-- workspace's window stack and concatenating these lists for all visible</span>
<a name="line-509"></a><span class='hs-comment'>-- workspaces.)</span>
<a name="line-510"></a><span class='hs-definition'>doFocusClosestWindow</span> <span class='hs-keyglyph'>::</span> <span class='hs-conid'>WinRect</span>
<a name="line-511"></a>                     <span class='hs-keyglyph'>-&gt;</span> <span class='hs-keyglyph'>[</span><span class='hs-conid'>WinRect</span><span class='hs-keyglyph'>]</span>
<a name="line-512"></a>                     <span class='hs-keyglyph'>-&gt;</span> <span class='hs-layout'>(</span><span class='hs-conid'>WindowSet</span> <span class='hs-keyglyph'>-&gt;</span> <span class='hs-conid'>WindowSet</span><span class='hs-layout'>)</span>
<a name="line-513"></a><span class='hs-definition'>doFocusClosestWindow</span> <span class='hs-layout'>(</span><span class='hs-varid'>cur</span><span class='hs-layout'>,</span> <span class='hs-varid'>rect</span><span class='hs-layout'>)</span> <span class='hs-varid'>winrects</span>
<a name="line-514"></a>  <span class='hs-keyglyph'>|</span> <span class='hs-varid'>null</span> <span class='hs-varid'>winctrs</span> <span class='hs-keyglyph'>=</span> <span class='hs-varid'>id</span>
<a name="line-515"></a>  <span class='hs-keyglyph'>|</span> <span class='hs-varid'>otherwise</span>    <span class='hs-keyglyph'>=</span> <span class='hs-conid'>W</span><span class='hs-varop'>.</span><span class='hs-varid'>focusWindow</span> <span class='hs-varop'>.</span> <span class='hs-varid'>fst</span> <span class='hs-varop'>$</span> <span class='hs-conid'>L</span><span class='hs-varop'>.</span><span class='hs-varid'>foldl1'</span> <span class='hs-varid'>closer</span> <span class='hs-varid'>winctrs</span>
<a name="line-516"></a>  <span class='hs-keyword'>where</span>
<a name="line-517"></a>    <span class='hs-varid'>ctr</span>     <span class='hs-keyglyph'>=</span> <span class='hs-varid'>centerOf</span> <span class='hs-varid'>rect</span>
<a name="line-518"></a>    <span class='hs-varid'>winctrs</span> <span class='hs-keyglyph'>=</span> <span class='hs-varid'>filter</span> <span class='hs-layout'>(</span><span class='hs-layout'>(</span><span class='hs-varid'>cur</span> <span class='hs-varop'>/=</span><span class='hs-layout'>)</span> <span class='hs-varop'>.</span> <span class='hs-varid'>fst</span><span class='hs-layout'>)</span>
<a name="line-519"></a>            <span class='hs-varop'>$</span> <span class='hs-varid'>map</span> <span class='hs-layout'>(</span><span class='hs-keyglyph'>\</span><span class='hs-layout'>(</span><span class='hs-varid'>w</span><span class='hs-layout'>,</span> <span class='hs-varid'>r</span><span class='hs-layout'>)</span> <span class='hs-keyglyph'>-&gt;</span> <span class='hs-layout'>(</span><span class='hs-varid'>w</span><span class='hs-layout'>,</span> <span class='hs-varid'>centerOf</span> <span class='hs-varid'>r</span><span class='hs-layout'>)</span><span class='hs-layout'>)</span> <span class='hs-varid'>winrects</span>
<a name="line-520"></a>    <span class='hs-varid'>closer</span> <span class='hs-varid'>wc1</span><span class='hs-keyglyph'>@</span><span class='hs-layout'>(</span><span class='hs-keyword'>_</span><span class='hs-layout'>,</span> <span class='hs-varid'>c1</span><span class='hs-layout'>)</span> <span class='hs-varid'>wc2</span><span class='hs-keyglyph'>@</span><span class='hs-layout'>(</span><span class='hs-keyword'>_</span><span class='hs-layout'>,</span> <span class='hs-varid'>c2</span><span class='hs-layout'>)</span> <span class='hs-keyglyph'>|</span> <span class='hs-varid'>lDist</span> <span class='hs-varid'>ctr</span> <span class='hs-varid'>c1</span> <span class='hs-varop'>&gt;</span> <span class='hs-varid'>lDist</span> <span class='hs-varid'>ctr</span> <span class='hs-varid'>c2</span> <span class='hs-keyglyph'>=</span> <span class='hs-varid'>wc2</span>
<a name="line-521"></a>                                   <span class='hs-keyglyph'>|</span> <span class='hs-varid'>otherwise</span>                   <span class='hs-keyglyph'>=</span> <span class='hs-varid'>wc1</span>
<a name="line-522"></a>
<a name="line-523"></a><a name="doTiledNavigation"></a><span class='hs-comment'>-- | Implements navigation for the tiled layer</span>
<a name="line-524"></a><span class='hs-definition'>doTiledNavigation</span> <span class='hs-keyglyph'>::</span> <span class='hs-conid'>Navigation2DConfig</span>
<a name="line-525"></a>                  <span class='hs-keyglyph'>-&gt;</span> <span class='hs-conid'>Direction2D</span>
<a name="line-526"></a>                  <span class='hs-keyglyph'>-&gt;</span> <span class='hs-layout'>(</span><span class='hs-conid'>Window</span> <span class='hs-keyglyph'>-&gt;</span> <span class='hs-conid'>WindowSet</span> <span class='hs-keyglyph'>-&gt;</span> <span class='hs-conid'>WindowSet</span><span class='hs-layout'>)</span>
<a name="line-527"></a>                  <span class='hs-keyglyph'>-&gt;</span> <span class='hs-conid'>WinRect</span>
<a name="line-528"></a>                  <span class='hs-keyglyph'>-&gt;</span> <span class='hs-keyglyph'>[</span><span class='hs-conid'>WinRect</span><span class='hs-keyglyph'>]</span>
<a name="line-529"></a>                  <span class='hs-keyglyph'>-&gt;</span> <span class='hs-layout'>(</span><span class='hs-conid'>WindowSet</span> <span class='hs-keyglyph'>-&gt;</span> <span class='hs-conid'>WindowSet</span><span class='hs-layout'>)</span>
<a name="line-530"></a><span class='hs-definition'>doTiledNavigation</span> <span class='hs-varid'>conf</span> <span class='hs-varid'>dir</span> <span class='hs-varid'>act</span> <span class='hs-varid'>cur</span> <span class='hs-varid'>winrects</span> <span class='hs-varid'>winset</span>
<a name="line-531"></a>  <span class='hs-keyglyph'>|</span> <span class='hs-conid'>Just</span> <span class='hs-varid'>win</span> <span class='hs-keyglyph'>&lt;-</span> <span class='hs-varid'>runNav</span> <span class='hs-varid'>nav</span> <span class='hs-varid'>dir</span> <span class='hs-varid'>cur</span> <span class='hs-varid'>winrects</span> <span class='hs-keyglyph'>=</span> <span class='hs-varid'>act</span> <span class='hs-varid'>win</span> <span class='hs-varid'>winset</span>
<a name="line-532"></a>  <span class='hs-keyglyph'>|</span> <span class='hs-varid'>otherwise</span>                               <span class='hs-keyglyph'>=</span> <span class='hs-varid'>winset</span>
<a name="line-533"></a>  <span class='hs-keyword'>where</span>
<a name="line-534"></a>    <span class='hs-varid'>layouts</span> <span class='hs-keyglyph'>=</span> <span class='hs-varid'>map</span> <span class='hs-layout'>(</span><span class='hs-varid'>description</span> <span class='hs-varop'>.</span> <span class='hs-conid'>W</span><span class='hs-varop'>.</span><span class='hs-varid'>layout</span> <span class='hs-varop'>.</span> <span class='hs-conid'>W</span><span class='hs-varop'>.</span><span class='hs-varid'>workspace</span><span class='hs-layout'>)</span>
<a name="line-535"></a>            <span class='hs-varop'>$</span> <span class='hs-conid'>W</span><span class='hs-varop'>.</span><span class='hs-varid'>screens</span> <span class='hs-varid'>winset</span>
<a name="line-536"></a>    <span class='hs-varid'>nav</span>     <span class='hs-keyglyph'>=</span> <span class='hs-varid'>maximum</span>
<a name="line-537"></a>            <span class='hs-varop'>$</span> <span class='hs-varid'>map</span> <span class='hs-layout'>(</span> <span class='hs-varid'>fromMaybe</span> <span class='hs-layout'>(</span><span class='hs-varid'>defaultTiledNavigation</span> <span class='hs-varid'>conf</span><span class='hs-layout'>)</span>
<a name="line-538"></a>                  <span class='hs-varop'>.</span> <span class='hs-varid'>flip</span> <span class='hs-conid'>L</span><span class='hs-varop'>.</span><span class='hs-varid'>lookup</span> <span class='hs-layout'>(</span><span class='hs-varid'>layoutNavigation</span> <span class='hs-varid'>conf</span><span class='hs-layout'>)</span>
<a name="line-539"></a>                  <span class='hs-layout'>)</span>
<a name="line-540"></a>            <span class='hs-varop'>$</span> <span class='hs-varid'>layouts</span>
<a name="line-541"></a>
<a name="line-542"></a><a name="doFloatNavigation"></a><span class='hs-comment'>-- | Implements navigation for the float layer</span>
<a name="line-543"></a><span class='hs-definition'>doFloatNavigation</span> <span class='hs-keyglyph'>::</span> <span class='hs-conid'>Navigation2DConfig</span>
<a name="line-544"></a>                  <span class='hs-keyglyph'>-&gt;</span> <span class='hs-conid'>Direction2D</span>
<a name="line-545"></a>                  <span class='hs-keyglyph'>-&gt;</span> <span class='hs-layout'>(</span><span class='hs-conid'>Window</span> <span class='hs-keyglyph'>-&gt;</span> <span class='hs-conid'>WindowSet</span> <span class='hs-keyglyph'>-&gt;</span> <span class='hs-conid'>WindowSet</span><span class='hs-layout'>)</span>
<a name="line-546"></a>                  <span class='hs-keyglyph'>-&gt;</span> <span class='hs-conid'>WinRect</span>
<a name="line-547"></a>                  <span class='hs-keyglyph'>-&gt;</span> <span class='hs-keyglyph'>[</span><span class='hs-conid'>WinRect</span><span class='hs-keyglyph'>]</span>
<a name="line-548"></a>                  <span class='hs-keyglyph'>-&gt;</span> <span class='hs-layout'>(</span><span class='hs-conid'>WindowSet</span> <span class='hs-keyglyph'>-&gt;</span> <span class='hs-conid'>WindowSet</span><span class='hs-layout'>)</span>
<a name="line-549"></a><span class='hs-definition'>doFloatNavigation</span> <span class='hs-varid'>conf</span> <span class='hs-varid'>dir</span> <span class='hs-varid'>act</span> <span class='hs-varid'>cur</span> <span class='hs-varid'>winrects</span>
<a name="line-550"></a>  <span class='hs-keyglyph'>|</span> <span class='hs-conid'>Just</span> <span class='hs-varid'>win</span> <span class='hs-keyglyph'>&lt;-</span> <span class='hs-varid'>runNav</span> <span class='hs-varid'>nav</span> <span class='hs-varid'>dir</span> <span class='hs-varid'>cur</span> <span class='hs-varid'>winrects</span> <span class='hs-keyglyph'>=</span> <span class='hs-varid'>act</span> <span class='hs-varid'>win</span>
<a name="line-551"></a>  <span class='hs-keyglyph'>|</span> <span class='hs-varid'>otherwise</span>                               <span class='hs-keyglyph'>=</span> <span class='hs-varid'>id</span>
<a name="line-552"></a>  <span class='hs-keyword'>where</span>
<a name="line-553"></a>    <span class='hs-varid'>nav</span> <span class='hs-keyglyph'>=</span> <span class='hs-varid'>floatNavigation</span> <span class='hs-varid'>conf</span>
<a name="line-554"></a>
<a name="line-555"></a><a name="doScreenNavigation"></a><span class='hs-comment'>-- | Implements navigation between screens</span>
<a name="line-556"></a><span class='hs-definition'>doScreenNavigation</span> <span class='hs-keyglyph'>::</span> <span class='hs-conid'>Navigation2DConfig</span>
<a name="line-557"></a>                   <span class='hs-keyglyph'>-&gt;</span> <span class='hs-conid'>Direction2D</span>
<a name="line-558"></a>                   <span class='hs-keyglyph'>-&gt;</span> <span class='hs-layout'>(</span><span class='hs-conid'>WorkspaceId</span> <span class='hs-keyglyph'>-&gt;</span> <span class='hs-conid'>WindowSet</span> <span class='hs-keyglyph'>-&gt;</span> <span class='hs-conid'>WindowSet</span><span class='hs-layout'>)</span>
<a name="line-559"></a>                   <span class='hs-keyglyph'>-&gt;</span> <span class='hs-conid'>WSRect</span>
<a name="line-560"></a>                   <span class='hs-keyglyph'>-&gt;</span> <span class='hs-keyglyph'>[</span><span class='hs-conid'>WSRect</span><span class='hs-keyglyph'>]</span>
<a name="line-561"></a>                   <span class='hs-keyglyph'>-&gt;</span> <span class='hs-layout'>(</span><span class='hs-conid'>WindowSet</span> <span class='hs-keyglyph'>-&gt;</span> <span class='hs-conid'>WindowSet</span><span class='hs-layout'>)</span>
<a name="line-562"></a><span class='hs-definition'>doScreenNavigation</span> <span class='hs-varid'>conf</span> <span class='hs-varid'>dir</span> <span class='hs-varid'>act</span> <span class='hs-varid'>cur</span> <span class='hs-varid'>wsrects</span>
<a name="line-563"></a>  <span class='hs-keyglyph'>|</span> <span class='hs-conid'>Just</span> <span class='hs-varid'>ws</span> <span class='hs-keyglyph'>&lt;-</span> <span class='hs-varid'>runNav</span> <span class='hs-varid'>nav</span> <span class='hs-varid'>dir</span> <span class='hs-varid'>cur</span> <span class='hs-varid'>wsrects</span> <span class='hs-keyglyph'>=</span> <span class='hs-varid'>act</span> <span class='hs-varid'>ws</span>
<a name="line-564"></a>  <span class='hs-keyglyph'>|</span> <span class='hs-varid'>otherwise</span>                             <span class='hs-keyglyph'>=</span> <span class='hs-varid'>id</span>
<a name="line-565"></a>  <span class='hs-keyword'>where</span>
<a name="line-566"></a>    <span class='hs-varid'>nav</span> <span class='hs-keyglyph'>=</span> <span class='hs-varid'>screenNavigation</span> <span class='hs-varid'>conf</span>
<a name="line-567"></a>
<a name="line-568"></a><a name="doLineNavigation"></a><span class='hs-comment'>-- | Implements line navigation.  For layouts without overlapping windows, there</span>
<a name="line-569"></a><span class='hs-comment'>-- is no need to break ties between equidistant windows.  When windows do</span>
<a name="line-570"></a><span class='hs-comment'>-- overlap, even the best tie breaking rule cannot make line navigation feel</span>
<a name="line-571"></a><span class='hs-comment'>-- natural.  Thus, we fairly arbtitrarily break ties by preferring the window</span>
<a name="line-572"></a><span class='hs-comment'>-- that comes first in the window stack.  (The stack order is the one produced</span>
<a name="line-573"></a><span class='hs-comment'>-- by integrate'ing each visible workspace's window stack and concatenating</span>
<a name="line-574"></a><span class='hs-comment'>-- these lists for all visible workspaces.)</span>
<a name="line-575"></a><span class='hs-definition'>doLineNavigation</span> <span class='hs-keyglyph'>::</span> <span class='hs-conid'>Eq</span> <span class='hs-varid'>a</span> <span class='hs-keyglyph'>=&gt;</span> <span class='hs-conid'>Direction2D</span> <span class='hs-keyglyph'>-&gt;</span> <span class='hs-conid'>Rect</span> <span class='hs-varid'>a</span> <span class='hs-keyglyph'>-&gt;</span> <span class='hs-keyglyph'>[</span><span class='hs-conid'>Rect</span> <span class='hs-varid'>a</span><span class='hs-keyglyph'>]</span> <span class='hs-keyglyph'>-&gt;</span> <span class='hs-conid'>Maybe</span> <span class='hs-varid'>a</span>
<a name="line-576"></a><span class='hs-definition'>doLineNavigation</span> <span class='hs-varid'>dir</span> <span class='hs-layout'>(</span><span class='hs-varid'>cur</span><span class='hs-layout'>,</span> <span class='hs-varid'>rect</span><span class='hs-layout'>)</span> <span class='hs-varid'>winrects</span>
<a name="line-577"></a>  <span class='hs-keyglyph'>|</span> <span class='hs-varid'>null</span> <span class='hs-varid'>winrects'</span> <span class='hs-keyglyph'>=</span> <span class='hs-conid'>Nothing</span>
<a name="line-578"></a>  <span class='hs-keyglyph'>|</span> <span class='hs-varid'>otherwise</span>      <span class='hs-keyglyph'>=</span> <span class='hs-conid'>Just</span> <span class='hs-varop'>.</span> <span class='hs-varid'>fst</span> <span class='hs-varop'>$</span> <span class='hs-conid'>L</span><span class='hs-varop'>.</span><span class='hs-varid'>foldl1'</span> <span class='hs-varid'>closer</span> <span class='hs-varid'>winrects'</span>
<a name="line-579"></a>  <span class='hs-keyword'>where</span>
<a name="line-580"></a>    <span class='hs-comment'>-- The current window's center</span>
<a name="line-581"></a>    <span class='hs-varid'>ctr</span><span class='hs-keyglyph'>@</span><span class='hs-layout'>(</span><span class='hs-varid'>xc</span><span class='hs-layout'>,</span> <span class='hs-varid'>yc</span><span class='hs-layout'>)</span>  <span class='hs-keyglyph'>=</span> <span class='hs-varid'>centerOf</span> <span class='hs-varid'>rect</span>
<a name="line-582"></a>
<a name="line-583"></a>    <span class='hs-comment'>-- The list of windows that are candidates to receive focus.</span>
<a name="line-584"></a>    <span class='hs-varid'>winrects'</span>     <span class='hs-keyglyph'>=</span> <span class='hs-varid'>filter</span> <span class='hs-varid'>dirFilter</span>
<a name="line-585"></a>                  <span class='hs-varop'>$</span> <span class='hs-varid'>filter</span> <span class='hs-layout'>(</span><span class='hs-layout'>(</span><span class='hs-varid'>cur</span> <span class='hs-varop'>/=</span><span class='hs-layout'>)</span> <span class='hs-varop'>.</span> <span class='hs-varid'>fst</span><span class='hs-layout'>)</span>
<a name="line-586"></a>                  <span class='hs-varop'>$</span> <span class='hs-varid'>winrects</span>
<a name="line-587"></a>
<a name="line-588"></a>    <span class='hs-comment'>-- Decides whether a given window matches the criteria to be a candidate to</span>
<a name="line-589"></a>    <span class='hs-comment'>-- receive the focus.</span>
<a name="line-590"></a>    <span class='hs-varid'>dirFilter</span> <span class='hs-layout'>(</span><span class='hs-keyword'>_</span><span class='hs-layout'>,</span> <span class='hs-varid'>r</span><span class='hs-layout'>)</span> <span class='hs-keyglyph'>=</span>  <span class='hs-layout'>(</span><span class='hs-varid'>dir</span> <span class='hs-varop'>==</span> <span class='hs-conid'>L</span> <span class='hs-varop'>&amp;&amp;</span> <span class='hs-varid'>leftOf</span> <span class='hs-varid'>r</span> <span class='hs-varid'>rect</span> <span class='hs-varop'>&amp;&amp;</span> <span class='hs-varid'>intersectsY</span> <span class='hs-varid'>yc</span> <span class='hs-varid'>r</span><span class='hs-layout'>)</span>
<a name="line-591"></a>                     <span class='hs-varop'>||</span> <span class='hs-layout'>(</span><span class='hs-varid'>dir</span> <span class='hs-varop'>==</span> <span class='hs-conid'>R</span> <span class='hs-varop'>&amp;&amp;</span> <span class='hs-varid'>leftOf</span> <span class='hs-varid'>rect</span> <span class='hs-varid'>r</span> <span class='hs-varop'>&amp;&amp;</span> <span class='hs-varid'>intersectsY</span> <span class='hs-varid'>yc</span> <span class='hs-varid'>r</span><span class='hs-layout'>)</span>
<a name="line-592"></a>                     <span class='hs-varop'>||</span> <span class='hs-layout'>(</span><span class='hs-varid'>dir</span> <span class='hs-varop'>==</span> <span class='hs-conid'>U</span> <span class='hs-varop'>&amp;&amp;</span> <span class='hs-varid'>above</span>  <span class='hs-varid'>r</span> <span class='hs-varid'>rect</span> <span class='hs-varop'>&amp;&amp;</span> <span class='hs-varid'>intersectsX</span> <span class='hs-varid'>xc</span> <span class='hs-varid'>r</span><span class='hs-layout'>)</span>
<a name="line-593"></a>                     <span class='hs-varop'>||</span> <span class='hs-layout'>(</span><span class='hs-varid'>dir</span> <span class='hs-varop'>==</span> <span class='hs-conid'>D</span> <span class='hs-varop'>&amp;&amp;</span> <span class='hs-varid'>above</span>  <span class='hs-varid'>rect</span> <span class='hs-varid'>r</span> <span class='hs-varop'>&amp;&amp;</span> <span class='hs-varid'>intersectsX</span> <span class='hs-varid'>xc</span> <span class='hs-varid'>r</span><span class='hs-layout'>)</span>
<a name="line-594"></a>
<a name="line-595"></a>    <span class='hs-comment'>-- Decide whether r1 is left of/above r2.</span>
<a name="line-596"></a>    <span class='hs-varid'>leftOf</span> <span class='hs-varid'>r1</span> <span class='hs-varid'>r2</span> <span class='hs-keyglyph'>=</span> <span class='hs-varid'>rect_x</span> <span class='hs-varid'>r1</span> <span class='hs-varop'>+</span> <span class='hs-varid'>fi</span> <span class='hs-layout'>(</span><span class='hs-varid'>rect_width</span>  <span class='hs-varid'>r1</span><span class='hs-layout'>)</span> <span class='hs-varop'>&lt;=</span> <span class='hs-varid'>rect_x</span> <span class='hs-varid'>r2</span>
<a name="line-597"></a>    <span class='hs-varid'>above</span>  <span class='hs-varid'>r1</span> <span class='hs-varid'>r2</span> <span class='hs-keyglyph'>=</span> <span class='hs-varid'>rect_y</span> <span class='hs-varid'>r1</span> <span class='hs-varop'>+</span> <span class='hs-varid'>fi</span> <span class='hs-layout'>(</span><span class='hs-varid'>rect_height</span> <span class='hs-varid'>r1</span><span class='hs-layout'>)</span> <span class='hs-varop'>&lt;=</span> <span class='hs-varid'>rect_y</span> <span class='hs-varid'>r2</span>
<a name="line-598"></a>
<a name="line-599"></a>    <span class='hs-comment'>-- Check whether r's x-/y-range contains the given x-/y-coordinate.</span>
<a name="line-600"></a>    <span class='hs-varid'>intersectsX</span> <span class='hs-varid'>x</span> <span class='hs-varid'>r</span> <span class='hs-keyglyph'>=</span> <span class='hs-varid'>rect_x</span> <span class='hs-varid'>r</span> <span class='hs-varop'>&lt;=</span> <span class='hs-varid'>x</span> <span class='hs-varop'>&amp;&amp;</span> <span class='hs-varid'>rect_x</span> <span class='hs-varid'>r</span> <span class='hs-varop'>+</span> <span class='hs-varid'>fi</span> <span class='hs-layout'>(</span><span class='hs-varid'>rect_width</span>  <span class='hs-varid'>r</span><span class='hs-layout'>)</span> <span class='hs-varop'>&gt;=</span> <span class='hs-varid'>x</span>
<a name="line-601"></a>    <span class='hs-varid'>intersectsY</span> <span class='hs-varid'>y</span> <span class='hs-varid'>r</span> <span class='hs-keyglyph'>=</span> <span class='hs-varid'>rect_y</span> <span class='hs-varid'>r</span> <span class='hs-varop'>&lt;=</span> <span class='hs-varid'>y</span> <span class='hs-varop'>&amp;&amp;</span> <span class='hs-varid'>rect_y</span> <span class='hs-varid'>r</span> <span class='hs-varop'>+</span> <span class='hs-varid'>fi</span> <span class='hs-layout'>(</span><span class='hs-varid'>rect_height</span> <span class='hs-varid'>r</span><span class='hs-layout'>)</span> <span class='hs-varop'>&gt;=</span> <span class='hs-varid'>y</span>
<a name="line-602"></a>
<a name="line-603"></a>    <span class='hs-comment'>-- Decides whether r1 is closer to the current window's center than r2</span>
<a name="line-604"></a>    <span class='hs-varid'>closer</span> <span class='hs-varid'>wr1</span><span class='hs-keyglyph'>@</span><span class='hs-layout'>(</span><span class='hs-keyword'>_</span><span class='hs-layout'>,</span> <span class='hs-varid'>r1</span><span class='hs-layout'>)</span> <span class='hs-varid'>wr2</span><span class='hs-keyglyph'>@</span><span class='hs-layout'>(</span><span class='hs-keyword'>_</span><span class='hs-layout'>,</span> <span class='hs-varid'>r2</span><span class='hs-layout'>)</span> <span class='hs-keyglyph'>|</span> <span class='hs-varid'>dist</span> <span class='hs-varid'>ctr</span> <span class='hs-varid'>r1</span> <span class='hs-varop'>&gt;</span> <span class='hs-varid'>dist</span> <span class='hs-varid'>ctr</span> <span class='hs-varid'>r2</span> <span class='hs-keyglyph'>=</span> <span class='hs-varid'>wr2</span>
<a name="line-605"></a>                                   <span class='hs-keyglyph'>|</span> <span class='hs-varid'>otherwise</span>                 <span class='hs-keyglyph'>=</span> <span class='hs-varid'>wr1</span>
<a name="line-606"></a>
<a name="line-607"></a>    <span class='hs-comment'>-- Returns the distance of r from the point (x, y)</span>
<a name="line-608"></a>    <span class='hs-varid'>dist</span> <span class='hs-layout'>(</span><span class='hs-varid'>x</span><span class='hs-layout'>,</span> <span class='hs-varid'>y</span><span class='hs-layout'>)</span> <span class='hs-varid'>r</span> <span class='hs-keyglyph'>|</span> <span class='hs-varid'>dir</span> <span class='hs-varop'>==</span> <span class='hs-conid'>L</span>  <span class='hs-keyglyph'>=</span> <span class='hs-varid'>x</span> <span class='hs-comment'>-</span> <span class='hs-varid'>rect_x</span> <span class='hs-varid'>r</span> <span class='hs-comment'>-</span> <span class='hs-varid'>fi</span> <span class='hs-layout'>(</span><span class='hs-varid'>rect_width</span> <span class='hs-varid'>r</span><span class='hs-layout'>)</span>
<a name="line-609"></a>                  <span class='hs-keyglyph'>|</span> <span class='hs-varid'>dir</span> <span class='hs-varop'>==</span> <span class='hs-conid'>R</span>  <span class='hs-keyglyph'>=</span> <span class='hs-varid'>rect_x</span> <span class='hs-varid'>r</span> <span class='hs-comment'>-</span> <span class='hs-varid'>x</span>
<a name="line-610"></a>                  <span class='hs-keyglyph'>|</span> <span class='hs-varid'>dir</span> <span class='hs-varop'>==</span> <span class='hs-conid'>U</span>  <span class='hs-keyglyph'>=</span> <span class='hs-varid'>y</span> <span class='hs-comment'>-</span> <span class='hs-varid'>rect_y</span> <span class='hs-varid'>r</span> <span class='hs-comment'>-</span> <span class='hs-varid'>fi</span> <span class='hs-layout'>(</span><span class='hs-varid'>rect_height</span> <span class='hs-varid'>r</span><span class='hs-layout'>)</span>
<a name="line-611"></a>                  <span class='hs-keyglyph'>|</span> <span class='hs-varid'>otherwise</span> <span class='hs-keyglyph'>=</span> <span class='hs-varid'>rect_y</span> <span class='hs-varid'>r</span> <span class='hs-comment'>-</span> <span class='hs-varid'>y</span>
<a name="line-612"></a>
<a name="line-613"></a><a name="doCenterNavigation"></a><span class='hs-comment'>-- | Implements center navigation</span>
<a name="line-614"></a><span class='hs-definition'>doCenterNavigation</span> <span class='hs-keyglyph'>::</span> <span class='hs-conid'>Eq</span> <span class='hs-varid'>a</span> <span class='hs-keyglyph'>=&gt;</span> <span class='hs-conid'>Direction2D</span> <span class='hs-keyglyph'>-&gt;</span> <span class='hs-conid'>Rect</span> <span class='hs-varid'>a</span> <span class='hs-keyglyph'>-&gt;</span> <span class='hs-keyglyph'>[</span><span class='hs-conid'>Rect</span> <span class='hs-varid'>a</span><span class='hs-keyglyph'>]</span> <span class='hs-keyglyph'>-&gt;</span> <span class='hs-conid'>Maybe</span> <span class='hs-varid'>a</span>
<a name="line-615"></a><span class='hs-definition'>doCenterNavigation</span> <span class='hs-varid'>dir</span> <span class='hs-layout'>(</span><span class='hs-varid'>cur</span><span class='hs-layout'>,</span> <span class='hs-varid'>rect</span><span class='hs-layout'>)</span> <span class='hs-varid'>winrects</span>
<a name="line-616"></a>  <span class='hs-keyglyph'>|</span> <span class='hs-layout'>(</span><span class='hs-layout'>(</span><span class='hs-varid'>w</span><span class='hs-layout'>,</span> <span class='hs-keyword'>_</span><span class='hs-layout'>)</span><span class='hs-conop'>:</span><span class='hs-keyword'>_</span><span class='hs-layout'>)</span> <span class='hs-keyglyph'>&lt;-</span> <span class='hs-varid'>onCtr'</span> <span class='hs-keyglyph'>=</span> <span class='hs-conid'>Just</span> <span class='hs-varid'>w</span>
<a name="line-617"></a>  <span class='hs-keyglyph'>|</span> <span class='hs-varid'>otherwise</span>            <span class='hs-keyglyph'>=</span> <span class='hs-varid'>closestOffCtr</span>
<a name="line-618"></a>  <span class='hs-keyword'>where</span>
<a name="line-619"></a>    <span class='hs-comment'>-- The center of the current window</span>
<a name="line-620"></a>    <span class='hs-layout'>(</span><span class='hs-varid'>xc</span><span class='hs-layout'>,</span> <span class='hs-varid'>yc</span><span class='hs-layout'>)</span> <span class='hs-keyglyph'>=</span> <span class='hs-varid'>centerOf</span> <span class='hs-varid'>rect</span>
<a name="line-621"></a>
<a name="line-622"></a>    <span class='hs-comment'>-- All the windows with their center points relative to the current</span>
<a name="line-623"></a>    <span class='hs-comment'>-- center rotated so the right cone becomes the relevant cone.</span>
<a name="line-624"></a>    <span class='hs-comment'>-- The windows are ordered in the order they should be preferred</span>
<a name="line-625"></a>    <span class='hs-comment'>-- when they are otherwise tied.</span>
<a name="line-626"></a>    <span class='hs-varid'>winctrs</span> <span class='hs-keyglyph'>=</span> <span class='hs-varid'>map</span> <span class='hs-layout'>(</span><span class='hs-keyglyph'>\</span><span class='hs-layout'>(</span><span class='hs-varid'>w</span><span class='hs-layout'>,</span> <span class='hs-varid'>r</span><span class='hs-layout'>)</span> <span class='hs-keyglyph'>-&gt;</span> <span class='hs-layout'>(</span><span class='hs-varid'>w</span><span class='hs-layout'>,</span> <span class='hs-varid'>dirTransform</span> <span class='hs-varop'>.</span> <span class='hs-varid'>centerOf</span> <span class='hs-varop'>$</span> <span class='hs-varid'>r</span><span class='hs-layout'>)</span><span class='hs-layout'>)</span>
<a name="line-627"></a>            <span class='hs-varop'>$</span> <span class='hs-varid'>stackTransform</span>
<a name="line-628"></a>            <span class='hs-varop'>$</span> <span class='hs-varid'>winrects</span>
<a name="line-629"></a>
<a name="line-630"></a>    <span class='hs-comment'>-- Give preference to windows later in the stack for going left or up and to</span>
<a name="line-631"></a>    <span class='hs-comment'>-- windows earlier in the stack for going right or down.  (The stack order</span>
<a name="line-632"></a>    <span class='hs-comment'>-- is the one produced by integrate'ing each visible workspace's window</span>
<a name="line-633"></a>    <span class='hs-comment'>-- stack and concatenating these lists for all visible workspaces.)</span>
<a name="line-634"></a>    <span class='hs-varid'>stackTransform</span> <span class='hs-keyglyph'>|</span> <span class='hs-varid'>dir</span> <span class='hs-varop'>==</span> <span class='hs-conid'>L</span> <span class='hs-varop'>||</span> <span class='hs-varid'>dir</span> <span class='hs-varop'>==</span> <span class='hs-conid'>U</span> <span class='hs-keyglyph'>=</span> <span class='hs-varid'>reverse</span>
<a name="line-635"></a>                   <span class='hs-keyglyph'>|</span> <span class='hs-varid'>otherwise</span>            <span class='hs-keyglyph'>=</span> <span class='hs-varid'>id</span>
<a name="line-636"></a>
<a name="line-637"></a>    <span class='hs-comment'>-- Transform a point into a difference to the current window center and</span>
<a name="line-638"></a>    <span class='hs-comment'>-- rotate it so that the relevant cone becomes the right cone.</span>
<a name="line-639"></a>    <span class='hs-varid'>dirTransform</span> <span class='hs-layout'>(</span><span class='hs-varid'>x</span><span class='hs-layout'>,</span> <span class='hs-varid'>y</span><span class='hs-layout'>)</span> <span class='hs-keyglyph'>|</span> <span class='hs-varid'>dir</span> <span class='hs-varop'>==</span> <span class='hs-conid'>R</span>  <span class='hs-keyglyph'>=</span> <span class='hs-layout'>(</span>  <span class='hs-varid'>x</span> <span class='hs-comment'>-</span> <span class='hs-varid'>xc</span> <span class='hs-layout'>,</span>   <span class='hs-varid'>y</span> <span class='hs-comment'>-</span> <span class='hs-varid'>yc</span> <span class='hs-layout'>)</span>
<a name="line-640"></a>                        <span class='hs-keyglyph'>|</span> <span class='hs-varid'>dir</span> <span class='hs-varop'>==</span> <span class='hs-conid'>L</span>  <span class='hs-keyglyph'>=</span> <span class='hs-layout'>(</span><span class='hs-comment'>-</span><span class='hs-layout'>(</span><span class='hs-varid'>x</span> <span class='hs-comment'>-</span> <span class='hs-varid'>xc</span><span class='hs-layout'>)</span><span class='hs-layout'>,</span> <span class='hs-comment'>-</span><span class='hs-layout'>(</span><span class='hs-varid'>y</span> <span class='hs-comment'>-</span> <span class='hs-varid'>yc</span><span class='hs-layout'>)</span><span class='hs-layout'>)</span>
<a name="line-641"></a>                        <span class='hs-keyglyph'>|</span> <span class='hs-varid'>dir</span> <span class='hs-varop'>==</span> <span class='hs-conid'>D</span>  <span class='hs-keyglyph'>=</span> <span class='hs-layout'>(</span>  <span class='hs-varid'>y</span> <span class='hs-comment'>-</span> <span class='hs-varid'>yc</span> <span class='hs-layout'>,</span>   <span class='hs-varid'>x</span> <span class='hs-comment'>-</span> <span class='hs-varid'>xc</span> <span class='hs-layout'>)</span>
<a name="line-642"></a>                        <span class='hs-keyglyph'>|</span> <span class='hs-varid'>otherwise</span> <span class='hs-keyglyph'>=</span> <span class='hs-layout'>(</span><span class='hs-comment'>-</span><span class='hs-layout'>(</span><span class='hs-varid'>y</span> <span class='hs-comment'>-</span> <span class='hs-varid'>yc</span><span class='hs-layout'>)</span><span class='hs-layout'>,</span> <span class='hs-comment'>-</span><span class='hs-layout'>(</span><span class='hs-varid'>x</span> <span class='hs-comment'>-</span> <span class='hs-varid'>xc</span><span class='hs-layout'>)</span><span class='hs-layout'>)</span>
<a name="line-643"></a>
<a name="line-644"></a>    <span class='hs-comment'>-- Partition the points into points that coincide with the center</span>
<a name="line-645"></a>    <span class='hs-comment'>-- and points that do not.</span>
<a name="line-646"></a>    <span class='hs-layout'>(</span><span class='hs-varid'>onCtr</span><span class='hs-layout'>,</span> <span class='hs-varid'>offCtr</span><span class='hs-layout'>)</span> <span class='hs-keyglyph'>=</span> <span class='hs-conid'>L</span><span class='hs-varop'>.</span><span class='hs-varid'>partition</span> <span class='hs-layout'>(</span><span class='hs-keyglyph'>\</span><span class='hs-layout'>(</span><span class='hs-keyword'>_</span><span class='hs-layout'>,</span> <span class='hs-layout'>(</span><span class='hs-varid'>x</span><span class='hs-layout'>,</span> <span class='hs-varid'>y</span><span class='hs-layout'>)</span><span class='hs-layout'>)</span> <span class='hs-keyglyph'>-&gt;</span> <span class='hs-varid'>x</span> <span class='hs-varop'>==</span> <span class='hs-num'>0</span> <span class='hs-varop'>&amp;&amp;</span> <span class='hs-varid'>y</span> <span class='hs-varop'>==</span> <span class='hs-num'>0</span><span class='hs-layout'>)</span> <span class='hs-varid'>winctrs</span>
<a name="line-647"></a>
<a name="line-648"></a>    <span class='hs-comment'>-- All the points that coincide with the current center and succeed it</span>
<a name="line-649"></a>    <span class='hs-comment'>-- in the (appropriately ordered) window stack.</span>
<a name="line-650"></a>    <span class='hs-varid'>onCtr'</span> <span class='hs-keyglyph'>=</span> <span class='hs-conid'>L</span><span class='hs-varop'>.</span><span class='hs-varid'>tail</span> <span class='hs-varop'>$</span> <span class='hs-conid'>L</span><span class='hs-varop'>.</span><span class='hs-varid'>dropWhile</span> <span class='hs-layout'>(</span><span class='hs-layout'>(</span><span class='hs-varid'>cur</span> <span class='hs-varop'>/=</span><span class='hs-layout'>)</span> <span class='hs-varop'>.</span> <span class='hs-varid'>fst</span><span class='hs-layout'>)</span> <span class='hs-varid'>onCtr</span>
<a name="line-651"></a>             <span class='hs-comment'>-- tail should be safe here because cur should be in onCtr</span>
<a name="line-652"></a>
<a name="line-653"></a>    <span class='hs-comment'>-- All the points that do not coincide with the current center and which</span>
<a name="line-654"></a>    <span class='hs-comment'>-- lie in the (rotated) right cone.</span>
<a name="line-655"></a>    <span class='hs-varid'>offCtr'</span> <span class='hs-keyglyph'>=</span> <span class='hs-conid'>L</span><span class='hs-varop'>.</span><span class='hs-varid'>filter</span> <span class='hs-layout'>(</span><span class='hs-keyglyph'>\</span><span class='hs-layout'>(</span><span class='hs-keyword'>_</span><span class='hs-layout'>,</span> <span class='hs-layout'>(</span><span class='hs-varid'>x</span><span class='hs-layout'>,</span> <span class='hs-varid'>y</span><span class='hs-layout'>)</span><span class='hs-layout'>)</span> <span class='hs-keyglyph'>-&gt;</span> <span class='hs-varid'>x</span> <span class='hs-varop'>&gt;</span> <span class='hs-num'>0</span> <span class='hs-varop'>&amp;&amp;</span> <span class='hs-varid'>y</span> <span class='hs-varop'>&lt;</span> <span class='hs-varid'>x</span> <span class='hs-varop'>&amp;&amp;</span> <span class='hs-varid'>y</span> <span class='hs-varop'>&gt;=</span> <span class='hs-comment'>-</span><span class='hs-varid'>x</span><span class='hs-layout'>)</span> <span class='hs-varid'>offCtr</span>
<a name="line-656"></a>
<a name="line-657"></a>    <span class='hs-comment'>-- The off-center point closest to the center and</span>
<a name="line-658"></a>    <span class='hs-comment'>-- closest to the bottom ray of the cone.  Nothing if no off-center</span>
<a name="line-659"></a>    <span class='hs-comment'>-- point is in the cone</span>
<a name="line-660"></a>    <span class='hs-varid'>closestOffCtr</span> <span class='hs-keyglyph'>=</span> <span class='hs-keyword'>if</span> <span class='hs-varid'>null</span> <span class='hs-varid'>offCtr'</span> <span class='hs-keyword'>then</span> <span class='hs-conid'>Nothing</span>
<a name="line-661"></a>                                    <span class='hs-keyword'>else</span> <span class='hs-conid'>Just</span> <span class='hs-varop'>$</span> <span class='hs-varid'>fst</span> <span class='hs-varop'>$</span> <span class='hs-conid'>L</span><span class='hs-varop'>.</span><span class='hs-varid'>foldl1'</span> <span class='hs-varid'>closest</span> <span class='hs-varid'>offCtr'</span>
<a name="line-662"></a>
<a name="line-663"></a>    <span class='hs-varid'>closest</span> <span class='hs-varid'>wp</span><span class='hs-keyglyph'>@</span><span class='hs-layout'>(</span><span class='hs-keyword'>_</span><span class='hs-layout'>,</span> <span class='hs-varid'>p</span><span class='hs-keyglyph'>@</span><span class='hs-layout'>(</span><span class='hs-keyword'>_</span><span class='hs-layout'>,</span> <span class='hs-varid'>yp</span><span class='hs-layout'>)</span><span class='hs-layout'>)</span> <span class='hs-varid'>wq</span><span class='hs-keyglyph'>@</span><span class='hs-layout'>(</span><span class='hs-keyword'>_</span><span class='hs-layout'>,</span> <span class='hs-varid'>q</span><span class='hs-keyglyph'>@</span><span class='hs-layout'>(</span><span class='hs-keyword'>_</span><span class='hs-layout'>,</span> <span class='hs-varid'>yq</span><span class='hs-layout'>)</span><span class='hs-layout'>)</span>
<a name="line-664"></a>      <span class='hs-keyglyph'>|</span> <span class='hs-varid'>lDist</span> <span class='hs-layout'>(</span><span class='hs-num'>0</span><span class='hs-layout'>,</span> <span class='hs-num'>0</span><span class='hs-layout'>)</span> <span class='hs-varid'>q</span> <span class='hs-varop'>&lt;</span> <span class='hs-varid'>lDist</span> <span class='hs-layout'>(</span><span class='hs-num'>0</span><span class='hs-layout'>,</span> <span class='hs-num'>0</span><span class='hs-layout'>)</span> <span class='hs-varid'>p</span> <span class='hs-keyglyph'>=</span> <span class='hs-varid'>wq</span> <span class='hs-comment'>-- q is closer than p</span>
<a name="line-665"></a>      <span class='hs-keyglyph'>|</span> <span class='hs-varid'>lDist</span> <span class='hs-layout'>(</span><span class='hs-num'>0</span><span class='hs-layout'>,</span> <span class='hs-num'>0</span><span class='hs-layout'>)</span> <span class='hs-varid'>p</span> <span class='hs-varop'>&lt;</span> <span class='hs-varid'>lDist</span> <span class='hs-layout'>(</span><span class='hs-num'>0</span><span class='hs-layout'>,</span> <span class='hs-num'>0</span><span class='hs-layout'>)</span> <span class='hs-varid'>q</span> <span class='hs-keyglyph'>=</span> <span class='hs-varid'>wp</span> <span class='hs-comment'>-- q is farther away than p</span>
<a name="line-666"></a>      <span class='hs-keyglyph'>|</span> <span class='hs-varid'>yq</span> <span class='hs-varop'>&lt;</span> <span class='hs-varid'>yp</span>                         <span class='hs-keyglyph'>=</span> <span class='hs-varid'>wq</span> <span class='hs-comment'>-- q is closer to the bottom ray than p</span>
<a name="line-667"></a>      <span class='hs-keyglyph'>|</span> <span class='hs-varid'>otherwise</span>                       <span class='hs-keyglyph'>=</span> <span class='hs-varid'>wp</span> <span class='hs-comment'>-- q is farther away from the bottom ray than p</span>
<a name="line-668"></a>                                             <span class='hs-comment'>-- or it has the same distance but comes later</span>
<a name="line-669"></a>                                             <span class='hs-comment'>-- in the window stack</span>
<a name="line-670"></a>
<a name="line-671"></a><a name="swap"></a><span class='hs-comment'>-- | Swaps the current window with the window given as argument</span>
<a name="line-672"></a><span class='hs-definition'>swap</span> <span class='hs-keyglyph'>::</span> <span class='hs-conid'>Window</span> <span class='hs-keyglyph'>-&gt;</span> <span class='hs-conid'>WindowSet</span> <span class='hs-keyglyph'>-&gt;</span> <span class='hs-conid'>WindowSet</span>
<a name="line-673"></a><span class='hs-definition'>swap</span> <span class='hs-varid'>win</span> <span class='hs-varid'>winset</span> <span class='hs-keyglyph'>=</span> <span class='hs-conid'>W</span><span class='hs-varop'>.</span><span class='hs-varid'>focusWindow</span> <span class='hs-varid'>cur</span>
<a name="line-674"></a>                <span class='hs-varop'>$</span> <span class='hs-conid'>L</span><span class='hs-varop'>.</span><span class='hs-varid'>foldl'</span> <span class='hs-layout'>(</span><span class='hs-varid'>flip</span> <span class='hs-conid'>W</span><span class='hs-varop'>.</span><span class='hs-varid'>focusWindow</span><span class='hs-layout'>)</span> <span class='hs-varid'>newwinset</span> <span class='hs-varid'>newfocused</span>
<a name="line-675"></a>  <span class='hs-keyword'>where</span>
<a name="line-676"></a>    <span class='hs-comment'>-- The current window</span>
<a name="line-677"></a>    <span class='hs-varid'>cur</span>      <span class='hs-keyglyph'>=</span> <span class='hs-varid'>fromJust</span> <span class='hs-varop'>$</span> <span class='hs-conid'>W</span><span class='hs-varop'>.</span><span class='hs-varid'>peek</span> <span class='hs-varid'>winset</span>
<a name="line-678"></a>
<a name="line-679"></a>    <span class='hs-comment'>-- All screens</span>
<a name="line-680"></a>    <span class='hs-varid'>scrs</span>     <span class='hs-keyglyph'>=</span> <span class='hs-conid'>W</span><span class='hs-varop'>.</span><span class='hs-varid'>screens</span> <span class='hs-varid'>winset</span>
<a name="line-681"></a>
<a name="line-682"></a>    <span class='hs-comment'>-- All visible workspaces</span>
<a name="line-683"></a>    <span class='hs-varid'>visws</span>    <span class='hs-keyglyph'>=</span> <span class='hs-varid'>map</span> <span class='hs-conid'>W</span><span class='hs-varop'>.</span><span class='hs-varid'>workspace</span> <span class='hs-varid'>scrs</span>
<a name="line-684"></a>
<a name="line-685"></a>    <span class='hs-comment'>-- The focused windows of the visible workspaces</span>
<a name="line-686"></a>    <span class='hs-varid'>focused</span>  <span class='hs-keyglyph'>=</span> <span class='hs-varid'>mapMaybe</span> <span class='hs-layout'>(</span><span class='hs-keyglyph'>\</span><span class='hs-varid'>ws</span> <span class='hs-keyglyph'>-&gt;</span> <span class='hs-conid'>W</span><span class='hs-varop'>.</span><span class='hs-varid'>focus</span> <span class='hs-varop'>&lt;$&gt;</span> <span class='hs-conid'>W</span><span class='hs-varop'>.</span><span class='hs-varid'>stack</span> <span class='hs-varid'>ws</span><span class='hs-layout'>)</span> <span class='hs-varid'>visws</span>
<a name="line-687"></a>
<a name="line-688"></a>    <span class='hs-comment'>-- The window lists of the visible workspaces</span>
<a name="line-689"></a>    <span class='hs-varid'>wins</span>     <span class='hs-keyglyph'>=</span> <span class='hs-varid'>map</span> <span class='hs-layout'>(</span><span class='hs-conid'>W</span><span class='hs-varop'>.</span><span class='hs-varid'>integrate'</span> <span class='hs-varop'>.</span> <span class='hs-conid'>W</span><span class='hs-varop'>.</span><span class='hs-varid'>stack</span><span class='hs-layout'>)</span> <span class='hs-varid'>visws</span>
<a name="line-690"></a>
<a name="line-691"></a>    <span class='hs-comment'>-- Update focused windows and window lists to reflect swap of windows.</span>
<a name="line-692"></a>    <span class='hs-varid'>newfocused</span> <span class='hs-keyglyph'>=</span> <span class='hs-varid'>map</span> <span class='hs-varid'>swapWins</span> <span class='hs-varid'>focused</span>
<a name="line-693"></a>    <span class='hs-varid'>newwins</span>    <span class='hs-keyglyph'>=</span> <span class='hs-varid'>map</span> <span class='hs-layout'>(</span><span class='hs-varid'>map</span> <span class='hs-varid'>swapWins</span><span class='hs-layout'>)</span> <span class='hs-varid'>wins</span>
<a name="line-694"></a>
<a name="line-695"></a>    <span class='hs-comment'>-- Replaces the current window with the argument window and vice versa.</span>
<a name="line-696"></a>    <span class='hs-varid'>swapWins</span> <span class='hs-varid'>x</span> <span class='hs-keyglyph'>|</span> <span class='hs-varid'>x</span> <span class='hs-varop'>==</span> <span class='hs-varid'>cur</span>  <span class='hs-keyglyph'>=</span> <span class='hs-varid'>win</span>
<a name="line-697"></a>               <span class='hs-keyglyph'>|</span> <span class='hs-varid'>x</span> <span class='hs-varop'>==</span> <span class='hs-varid'>win</span>  <span class='hs-keyglyph'>=</span> <span class='hs-varid'>cur</span>
<a name="line-698"></a>               <span class='hs-keyglyph'>|</span> <span class='hs-varid'>otherwise</span> <span class='hs-keyglyph'>=</span> <span class='hs-varid'>x</span>
<a name="line-699"></a>
<a name="line-700"></a>    <span class='hs-comment'>-- Reconstruct the workspaces' window stacks to reflect the swap.</span>
<a name="line-701"></a>    <span class='hs-varid'>newvisws</span>  <span class='hs-keyglyph'>=</span> <span class='hs-varid'>zipWith</span> <span class='hs-layout'>(</span><span class='hs-keyglyph'>\</span><span class='hs-varid'>ws</span> <span class='hs-varid'>wns</span> <span class='hs-keyglyph'>-&gt;</span> <span class='hs-varid'>ws</span> <span class='hs-layout'>{</span> <span class='hs-conid'>W</span><span class='hs-varop'>.</span><span class='hs-varid'>stack</span> <span class='hs-keyglyph'>=</span> <span class='hs-conid'>W</span><span class='hs-varop'>.</span><span class='hs-varid'>differentiate</span> <span class='hs-varid'>wns</span> <span class='hs-layout'>}</span><span class='hs-layout'>)</span> <span class='hs-varid'>visws</span> <span class='hs-varid'>newwins</span>
<a name="line-702"></a>    <span class='hs-varid'>newscrs</span>   <span class='hs-keyglyph'>=</span> <span class='hs-varid'>zipWith</span> <span class='hs-layout'>(</span><span class='hs-keyglyph'>\</span><span class='hs-varid'>scr</span> <span class='hs-varid'>ws</span> <span class='hs-keyglyph'>-&gt;</span> <span class='hs-varid'>scr</span> <span class='hs-layout'>{</span> <span class='hs-conid'>W</span><span class='hs-varop'>.</span><span class='hs-varid'>workspace</span> <span class='hs-keyglyph'>=</span> <span class='hs-varid'>ws</span> <span class='hs-layout'>}</span><span class='hs-layout'>)</span> <span class='hs-varid'>scrs</span> <span class='hs-varid'>newvisws</span>
<a name="line-703"></a>    <span class='hs-varid'>newwinset</span> <span class='hs-keyglyph'>=</span> <span class='hs-varid'>winset</span> <span class='hs-layout'>{</span> <span class='hs-conid'>W</span><span class='hs-varop'>.</span><span class='hs-varid'>current</span> <span class='hs-keyglyph'>=</span> <span class='hs-varid'>head</span> <span class='hs-varid'>newscrs</span>
<a name="line-704"></a>                       <span class='hs-layout'>,</span> <span class='hs-conid'>W</span><span class='hs-varop'>.</span><span class='hs-varid'>visible</span> <span class='hs-keyglyph'>=</span> <span class='hs-varid'>tail</span> <span class='hs-varid'>newscrs</span>
<a name="line-705"></a>                       <span class='hs-layout'>}</span>
<a name="line-706"></a>
<a name="line-707"></a><a name="centerOf"></a><span class='hs-comment'>-- | Calculates the center of a rectangle</span>
<a name="line-708"></a><span class='hs-definition'>centerOf</span> <span class='hs-keyglyph'>::</span> <span class='hs-conid'>Rectangle</span> <span class='hs-keyglyph'>-&gt;</span> <span class='hs-layout'>(</span><span class='hs-conid'>Position</span><span class='hs-layout'>,</span> <span class='hs-conid'>Position</span><span class='hs-layout'>)</span>
<a name="line-709"></a><span class='hs-definition'>centerOf</span> <span class='hs-varid'>r</span> <span class='hs-keyglyph'>=</span> <span class='hs-layout'>(</span><span class='hs-varid'>rect_x</span> <span class='hs-varid'>r</span> <span class='hs-varop'>+</span> <span class='hs-varid'>fi</span> <span class='hs-layout'>(</span><span class='hs-varid'>rect_width</span> <span class='hs-varid'>r</span><span class='hs-layout'>)</span> <span class='hs-varop'>`div`</span> <span class='hs-num'>2</span><span class='hs-layout'>,</span> <span class='hs-varid'>rect_y</span> <span class='hs-varid'>r</span> <span class='hs-varop'>+</span> <span class='hs-varid'>fi</span> <span class='hs-layout'>(</span><span class='hs-varid'>rect_height</span> <span class='hs-varid'>r</span><span class='hs-layout'>)</span> <span class='hs-varop'>`div`</span> <span class='hs-num'>2</span><span class='hs-layout'>)</span>
<a name="line-710"></a>
<a name="line-711"></a><a name="fi"></a><span class='hs-comment'>-- | Shorthand for integer conversions</span>
<a name="line-712"></a><span class='hs-definition'>fi</span> <span class='hs-keyglyph'>::</span> <span class='hs-layout'>(</span><span class='hs-conid'>Integral</span> <span class='hs-varid'>a</span><span class='hs-layout'>,</span> <span class='hs-conid'>Num</span> <span class='hs-varid'>b</span><span class='hs-layout'>)</span> <span class='hs-keyglyph'>=&gt;</span> <span class='hs-varid'>a</span> <span class='hs-keyglyph'>-&gt;</span> <span class='hs-varid'>b</span>
<a name="line-713"></a><span class='hs-definition'>fi</span> <span class='hs-keyglyph'>=</span> <span class='hs-varid'>fromIntegral</span>
<a name="line-714"></a>
<a name="line-715"></a><a name="thisLayer"></a><span class='hs-comment'>-- | Functions to choose the subset of windows to operate on</span>
<a name="line-716"></a><span class='hs-definition'>thisLayer</span><span class='hs-layout'>,</span> <span class='hs-varid'>otherLayer</span> <span class='hs-keyglyph'>::</span> <span class='hs-varid'>a</span> <span class='hs-keyglyph'>-&gt;</span> <span class='hs-varid'>a</span> <span class='hs-keyglyph'>-&gt;</span> <span class='hs-varid'>a</span>
<a name="line-717"></a><span class='hs-definition'>thisLayer</span>  <span class='hs-keyglyph'>=</span> <span class='hs-varid'>curry</span> <span class='hs-varid'>fst</span>
<a name="line-718"></a><a name="otherLayer"></a><span class='hs-definition'>otherLayer</span> <span class='hs-keyglyph'>=</span> <span class='hs-varid'>curry</span> <span class='hs-varid'>snd</span>
<a name="line-719"></a>
<a name="line-720"></a><a name="visibleWorkspaces"></a><span class='hs-comment'>-- | Returns the list of visible workspaces and their screen rects</span>
<a name="line-721"></a><span class='hs-definition'>visibleWorkspaces</span> <span class='hs-keyglyph'>::</span> <span class='hs-conid'>WindowSet</span> <span class='hs-keyglyph'>-&gt;</span> <span class='hs-conid'>Bool</span> <span class='hs-keyglyph'>-&gt;</span> <span class='hs-keyglyph'>[</span><span class='hs-conid'>WSRect</span><span class='hs-keyglyph'>]</span>
<a name="line-722"></a><span class='hs-definition'>visibleWorkspaces</span> <span class='hs-varid'>winset</span> <span class='hs-varid'>wrap</span> <span class='hs-keyglyph'>=</span> <span class='hs-varid'>addWrapping</span> <span class='hs-varid'>winset</span> <span class='hs-varid'>wrap</span>
<a name="line-723"></a>                              <span class='hs-varop'>$</span> <span class='hs-varid'>map</span> <span class='hs-layout'>(</span> <span class='hs-keyglyph'>\</span><span class='hs-varid'>scr</span> <span class='hs-keyglyph'>-&gt;</span> <span class='hs-layout'>(</span> <span class='hs-conid'>W</span><span class='hs-varop'>.</span><span class='hs-varid'>tag</span> <span class='hs-varop'>.</span> <span class='hs-conid'>W</span><span class='hs-varop'>.</span><span class='hs-varid'>workspace</span>         <span class='hs-varop'>$</span> <span class='hs-varid'>scr</span>
<a name="line-724"></a>                                              <span class='hs-layout'>,</span> <span class='hs-varid'>screenRect</span> <span class='hs-varop'>.</span> <span class='hs-conid'>W</span><span class='hs-varop'>.</span><span class='hs-varid'>screenDetail</span> <span class='hs-varop'>$</span> <span class='hs-varid'>scr</span>
<a name="line-725"></a>                                              <span class='hs-layout'>)</span>
<a name="line-726"></a>                                    <span class='hs-layout'>)</span>
<a name="line-727"></a>                              <span class='hs-varop'>$</span> <span class='hs-varid'>sortedScreens</span> <span class='hs-varid'>winset</span>
<a name="line-728"></a>
<a name="line-729"></a><a name="addWrapping"></a><span class='hs-comment'>-- | Creates five copies of each (window/workspace, rect) pair in the input: the</span>
<a name="line-730"></a><span class='hs-comment'>-- original and four offset one desktop size (desktop = collection of all</span>
<a name="line-731"></a><span class='hs-comment'>-- screens) to the left, to the right, up, and down.  Wrap-around at desktop</span>
<a name="line-732"></a><span class='hs-comment'>-- edges is implemented by navigating into these displaced copies.</span>
<a name="line-733"></a><span class='hs-definition'>addWrapping</span> <span class='hs-keyglyph'>::</span> <span class='hs-conid'>WindowSet</span> <span class='hs-comment'>-- ^ The window set, used to get the desktop size</span>
<a name="line-734"></a>            <span class='hs-keyglyph'>-&gt;</span> <span class='hs-conid'>Bool</span>      <span class='hs-comment'>-- ^ Should wrapping be used?  Do nothing if not.</span>
<a name="line-735"></a>            <span class='hs-keyglyph'>-&gt;</span> <span class='hs-keyglyph'>[</span><span class='hs-conid'>Rect</span> <span class='hs-varid'>a</span><span class='hs-keyglyph'>]</span>  <span class='hs-comment'>-- ^ Input set of (window/workspace, rect) pairs</span>
<a name="line-736"></a>            <span class='hs-keyglyph'>-&gt;</span> <span class='hs-keyglyph'>[</span><span class='hs-conid'>Rect</span> <span class='hs-varid'>a</span><span class='hs-keyglyph'>]</span>
<a name="line-737"></a><span class='hs-definition'>addWrapping</span> <span class='hs-keyword'>_</span>      <span class='hs-conid'>False</span> <span class='hs-varid'>wrects</span> <span class='hs-keyglyph'>=</span> <span class='hs-varid'>wrects</span>
<a name="line-738"></a><span class='hs-definition'>addWrapping</span> <span class='hs-varid'>winset</span> <span class='hs-conid'>True</span>  <span class='hs-varid'>wrects</span> <span class='hs-keyglyph'>=</span> <span class='hs-keyglyph'>[</span> <span class='hs-layout'>(</span><span class='hs-varid'>w</span><span class='hs-layout'>,</span> <span class='hs-varid'>r</span> <span class='hs-layout'>{</span> <span class='hs-varid'>rect_x</span> <span class='hs-keyglyph'>=</span> <span class='hs-varid'>rect_x</span> <span class='hs-varid'>r</span> <span class='hs-varop'>+</span> <span class='hs-varid'>fi</span> <span class='hs-varid'>x</span>
<a name="line-739"></a>                                          <span class='hs-layout'>,</span> <span class='hs-varid'>rect_y</span> <span class='hs-keyglyph'>=</span> <span class='hs-varid'>rect_y</span> <span class='hs-varid'>r</span> <span class='hs-varop'>+</span> <span class='hs-varid'>fi</span> <span class='hs-varid'>y</span>
<a name="line-740"></a>                                          <span class='hs-layout'>}</span>
<a name="line-741"></a>                                    <span class='hs-layout'>)</span>
<a name="line-742"></a>                                  <span class='hs-keyglyph'>|</span> <span class='hs-layout'>(</span><span class='hs-varid'>w</span><span class='hs-layout'>,</span> <span class='hs-varid'>r</span><span class='hs-layout'>)</span> <span class='hs-keyglyph'>&lt;-</span> <span class='hs-varid'>wrects</span>
<a name="line-743"></a>                                  <span class='hs-layout'>,</span> <span class='hs-layout'>(</span><span class='hs-varid'>x</span><span class='hs-layout'>,</span> <span class='hs-varid'>y</span><span class='hs-layout'>)</span>  <span class='hs-keyglyph'>&lt;-</span> <span class='hs-keyglyph'>[</span><span class='hs-layout'>(</span><span class='hs-num'>0</span><span class='hs-layout'>,</span> <span class='hs-num'>0</span><span class='hs-layout'>)</span><span class='hs-layout'>,</span> <span class='hs-layout'>(</span><span class='hs-comment'>-</span><span class='hs-varid'>xoff</span><span class='hs-layout'>,</span> <span class='hs-num'>0</span><span class='hs-layout'>)</span><span class='hs-layout'>,</span> <span class='hs-layout'>(</span><span class='hs-varid'>xoff</span><span class='hs-layout'>,</span> <span class='hs-num'>0</span><span class='hs-layout'>)</span><span class='hs-layout'>,</span> <span class='hs-layout'>(</span><span class='hs-num'>0</span><span class='hs-layout'>,</span> <span class='hs-comment'>-</span><span class='hs-varid'>yoff</span><span class='hs-layout'>)</span><span class='hs-layout'>,</span> <span class='hs-layout'>(</span><span class='hs-num'>0</span><span class='hs-layout'>,</span> <span class='hs-varid'>yoff</span><span class='hs-layout'>)</span><span class='hs-keyglyph'>]</span>
<a name="line-744"></a>                                  <span class='hs-keyglyph'>]</span>
<a name="line-745"></a>  <span class='hs-keyword'>where</span>
<a name="line-746"></a>    <span class='hs-layout'>(</span><span class='hs-varid'>xoff</span><span class='hs-layout'>,</span> <span class='hs-varid'>yoff</span><span class='hs-layout'>)</span> <span class='hs-keyglyph'>=</span> <span class='hs-varid'>wrapOffsets</span> <span class='hs-varid'>winset</span>
<a name="line-747"></a>
<a name="line-748"></a><a name="wrapOffsets"></a><span class='hs-comment'>-- | Calculates the offsets for window/screen coordinates for the duplication</span>
<a name="line-749"></a><span class='hs-comment'>-- of windows/workspaces that implements wrap-around.</span>
<a name="line-750"></a><span class='hs-definition'>wrapOffsets</span> <span class='hs-keyglyph'>::</span> <span class='hs-conid'>WindowSet</span> <span class='hs-keyglyph'>-&gt;</span> <span class='hs-layout'>(</span><span class='hs-conid'>Integer</span><span class='hs-layout'>,</span> <span class='hs-conid'>Integer</span><span class='hs-layout'>)</span>
<a name="line-751"></a><span class='hs-definition'>wrapOffsets</span> <span class='hs-varid'>winset</span> <span class='hs-keyglyph'>=</span> <span class='hs-layout'>(</span><span class='hs-varid'>max_x</span> <span class='hs-comment'>-</span> <span class='hs-varid'>min_x</span><span class='hs-layout'>,</span> <span class='hs-varid'>max_y</span> <span class='hs-comment'>-</span> <span class='hs-varid'>min_y</span><span class='hs-layout'>)</span>
<a name="line-752"></a>  <span class='hs-keyword'>where</span>
<a name="line-753"></a>    <span class='hs-varid'>min_x</span> <span class='hs-keyglyph'>=</span> <span class='hs-varid'>fi</span> <span class='hs-varop'>$</span> <span class='hs-varid'>minimum</span> <span class='hs-varop'>$</span> <span class='hs-varid'>map</span> <span class='hs-varid'>rect_x</span> <span class='hs-varid'>rects</span>
<a name="line-754"></a>    <span class='hs-varid'>min_y</span> <span class='hs-keyglyph'>=</span> <span class='hs-varid'>fi</span> <span class='hs-varop'>$</span> <span class='hs-varid'>minimum</span> <span class='hs-varop'>$</span> <span class='hs-varid'>map</span> <span class='hs-varid'>rect_y</span> <span class='hs-varid'>rects</span>
<a name="line-755"></a>    <span class='hs-varid'>max_x</span> <span class='hs-keyglyph'>=</span> <span class='hs-varid'>fi</span> <span class='hs-varop'>$</span> <span class='hs-varid'>maximum</span> <span class='hs-varop'>$</span> <span class='hs-varid'>map</span> <span class='hs-layout'>(</span><span class='hs-keyglyph'>\</span><span class='hs-varid'>r</span> <span class='hs-keyglyph'>-&gt;</span> <span class='hs-varid'>rect_x</span> <span class='hs-varid'>r</span> <span class='hs-varop'>+</span> <span class='hs-layout'>(</span><span class='hs-varid'>fi</span> <span class='hs-varop'>$</span> <span class='hs-varid'>rect_width</span>  <span class='hs-varid'>r</span><span class='hs-layout'>)</span><span class='hs-layout'>)</span> <span class='hs-varid'>rects</span>
<a name="line-756"></a>    <span class='hs-varid'>max_y</span> <span class='hs-keyglyph'>=</span> <span class='hs-varid'>fi</span> <span class='hs-varop'>$</span> <span class='hs-varid'>maximum</span> <span class='hs-varop'>$</span> <span class='hs-varid'>map</span> <span class='hs-layout'>(</span><span class='hs-keyglyph'>\</span><span class='hs-varid'>r</span> <span class='hs-keyglyph'>-&gt;</span> <span class='hs-varid'>rect_y</span> <span class='hs-varid'>r</span> <span class='hs-varop'>+</span> <span class='hs-layout'>(</span><span class='hs-varid'>fi</span> <span class='hs-varop'>$</span> <span class='hs-varid'>rect_height</span> <span class='hs-varid'>r</span><span class='hs-layout'>)</span><span class='hs-layout'>)</span> <span class='hs-varid'>rects</span>
<a name="line-757"></a>    <span class='hs-varid'>rects</span> <span class='hs-keyglyph'>=</span> <span class='hs-varid'>map</span> <span class='hs-varid'>snd</span> <span class='hs-varop'>$</span> <span class='hs-varid'>visibleWorkspaces</span> <span class='hs-varid'>winset</span> <span class='hs-conid'>False</span>
<a name="line-758"></a>
<a name="line-759"></a>
<a name="line-760"></a><a name="sortedScreens"></a><span class='hs-comment'>-- | Returns the list of screens sorted primarily by their centers'</span>
<a name="line-761"></a><span class='hs-comment'>-- x-coordinates and secondarily by their y-coordinates.</span>
<a name="line-762"></a><span class='hs-definition'>sortedScreens</span> <span class='hs-keyglyph'>::</span> <span class='hs-conid'>WindowSet</span> <span class='hs-keyglyph'>-&gt;</span> <span class='hs-keyglyph'>[</span><span class='hs-conid'>Screen</span><span class='hs-keyglyph'>]</span>
<a name="line-763"></a><span class='hs-definition'>sortedScreens</span> <span class='hs-varid'>winset</span> <span class='hs-keyglyph'>=</span> <span class='hs-conid'>L</span><span class='hs-varop'>.</span><span class='hs-varid'>sortBy</span> <span class='hs-varid'>cmp</span>
<a name="line-764"></a>                     <span class='hs-varop'>$</span> <span class='hs-conid'>W</span><span class='hs-varop'>.</span><span class='hs-varid'>screens</span> <span class='hs-varid'>winset</span>
<a name="line-765"></a>  <span class='hs-keyword'>where</span>
<a name="line-766"></a>    <span class='hs-varid'>cmp</span> <span class='hs-varid'>s1</span> <span class='hs-varid'>s2</span> <span class='hs-keyglyph'>|</span> <span class='hs-varid'>x1</span> <span class='hs-varop'>&lt;</span> <span class='hs-varid'>x2</span>   <span class='hs-keyglyph'>=</span> <span class='hs-conid'>LT</span>
<a name="line-767"></a>              <span class='hs-keyglyph'>|</span> <span class='hs-varid'>x1</span> <span class='hs-varop'>&gt;</span> <span class='hs-varid'>x2</span>   <span class='hs-keyglyph'>=</span> <span class='hs-conid'>GT</span>
<a name="line-768"></a>              <span class='hs-keyglyph'>|</span> <span class='hs-varid'>y1</span> <span class='hs-varop'>&lt;</span> <span class='hs-varid'>x2</span>   <span class='hs-keyglyph'>=</span> <span class='hs-conid'>LT</span>
<a name="line-769"></a>              <span class='hs-keyglyph'>|</span> <span class='hs-varid'>y1</span> <span class='hs-varop'>&gt;</span> <span class='hs-varid'>y2</span>   <span class='hs-keyglyph'>=</span> <span class='hs-conid'>GT</span>
<a name="line-770"></a>              <span class='hs-keyglyph'>|</span> <span class='hs-varid'>otherwise</span> <span class='hs-keyglyph'>=</span> <span class='hs-conid'>EQ</span>
<a name="line-771"></a>      <span class='hs-keyword'>where</span>
<a name="line-772"></a>        <span class='hs-layout'>(</span><span class='hs-varid'>x1</span><span class='hs-layout'>,</span> <span class='hs-varid'>y1</span><span class='hs-layout'>)</span> <span class='hs-keyglyph'>=</span> <span class='hs-varid'>centerOf</span> <span class='hs-layout'>(</span><span class='hs-varid'>screenRect</span> <span class='hs-varop'>.</span> <span class='hs-conid'>W</span><span class='hs-varop'>.</span><span class='hs-varid'>screenDetail</span> <span class='hs-varop'>$</span> <span class='hs-varid'>s1</span><span class='hs-layout'>)</span>
<a name="line-773"></a>        <span class='hs-layout'>(</span><span class='hs-varid'>x2</span><span class='hs-layout'>,</span> <span class='hs-varid'>y2</span><span class='hs-layout'>)</span> <span class='hs-keyglyph'>=</span> <span class='hs-varid'>centerOf</span> <span class='hs-layout'>(</span><span class='hs-varid'>screenRect</span> <span class='hs-varop'>.</span> <span class='hs-conid'>W</span><span class='hs-varop'>.</span><span class='hs-varid'>screenDetail</span> <span class='hs-varop'>$</span> <span class='hs-varid'>s2</span><span class='hs-layout'>)</span>
<a name="line-774"></a>
<a name="line-775"></a>
<a name="line-776"></a><a name="lDist"></a><span class='hs-comment'>-- | Calculates the L1-distance between two points.</span>
<a name="line-777"></a><span class='hs-definition'>lDist</span> <span class='hs-keyglyph'>::</span> <span class='hs-layout'>(</span><span class='hs-conid'>Position</span><span class='hs-layout'>,</span> <span class='hs-conid'>Position</span><span class='hs-layout'>)</span> <span class='hs-keyglyph'>-&gt;</span> <span class='hs-layout'>(</span><span class='hs-conid'>Position</span><span class='hs-layout'>,</span> <span class='hs-conid'>Position</span><span class='hs-layout'>)</span> <span class='hs-keyglyph'>-&gt;</span> <span class='hs-conid'>Int</span>
<a name="line-778"></a><span class='hs-definition'>lDist</span> <span class='hs-layout'>(</span><span class='hs-varid'>x1</span><span class='hs-layout'>,</span> <span class='hs-varid'>y1</span><span class='hs-layout'>)</span> <span class='hs-layout'>(</span><span class='hs-varid'>x2</span><span class='hs-layout'>,</span> <span class='hs-varid'>y2</span><span class='hs-layout'>)</span> <span class='hs-keyglyph'>=</span> <span class='hs-varid'>abs</span> <span class='hs-layout'>(</span><span class='hs-varid'>fi</span> <span class='hs-varop'>$</span> <span class='hs-varid'>x1</span> <span class='hs-comment'>-</span> <span class='hs-varid'>x2</span><span class='hs-layout'>)</span> <span class='hs-varop'>+</span> <span class='hs-varid'>abs</span> <span class='hs-layout'>(</span><span class='hs-varid'>fi</span> <span class='hs-varop'>$</span> <span class='hs-varid'>y1</span> <span class='hs-comment'>-</span> <span class='hs-varid'>y2</span><span class='hs-layout'>)</span>
</pre></body>
</html>