    -----------------------------------------------------------------------------
    -- |
    -- Module      :  XMonad.Actions.TiledWindowDragging
    -- Description :  Change the position of windows by dragging them.
    -- Copyright   :  (c) 2020 Leon Kowarschick
    -- License     :  BSD3-style (see LICENSE)
    --
    -- Maintainer  :  Leon Kowarschick. <thereal.elkowar@gmail.com>
    -- Stability   :  unstable
    -- Portability :  unportable
    --
    -- Provides an action that allows you to change the position of windows by dragging them around.
    --
    -----------------------------------------------------------------------------

    module XMonad.Actions.TiledWindowDragging
      (
      -- * Usage
      -- $usage
        dragWindow
      )
    where

    import           XMonad
    import           XMonad.Prelude
    import qualified XMonad.StackSet               as W
    import           XMonad.Layout.DraggingVisualizer

    -- $usage
    -- You can use this module with the following in your @~\/.xmonad\/xmonad.hs@:
    --
    -- > import XMonad.Actions.TiledWindowDragging
    -- > import XMonad.Layout.DraggingVisualizer
    --
    -- then edit your 'layoutHook' by adding the draggingVisualizer to your layout:
    --
    -- > myLayout = draggingVisualizer $ layoutHook def
    --
    -- Then add a mouse binding for 'dragWindow':
    --
    -- > , ((modMask .|. shiftMask, button1), dragWindow)
    --
    -- For detailed instructions on editing your mouse bindings, see
    -- "XMonad.Doc.Extending#Editing_mouse_bindings".

    -- | Create a mouse binding for this to be able to drag your windows around.
    -- You need "XMonad.Layout.DraggingVisualizer" for this to look good.
    dragWindow :: Window -> X ()
    dragWindow :: Window -> X ()
    dragWindow Window
    window = X Bool -> X () -> X ()
    whenX (Window -> X Bool
    isClient Window
    window) (X () -> X ()) -> X () -> X ()
    forall a b. (a -> b) -> a -> b
    $ (Display -> X ()) -> X ()
    forall a. (Display -> X a) -> X a
    withDisplay ((Display -> X ()) -> X ()) -> (Display -> X ()) -> X ()
    forall a b. (a -> b) -> a -> b
    $ \Display
    dpy ->
      Display -> Window -> (WindowAttributes -> X ()) -> X ()
    withWindowAttributes Display
    dpy Window
    window ((WindowAttributes -> X ()) -> X ())
    -> (WindowAttributes -> X ()) -> X ()
    forall a b. (a -> b) -> a -> b
    $ \WindowAttributes
    wa -> do
        Window -> X ()
    focus Window
    window
        (Int
    offsetX, Int
    offsetY)                    <- Window -> X (Int, Int)
    getPointerOffset Window
    window
        let (Int
    winX, Int
    winY, Int
    winWidth, Int
    winHeight)  = WindowAttributes -> (Int, Int, Int, Int)
    getWindowPlacement WindowAttributes
    wa

        (Position -> Position -> X ()) -> X () -> X ()
    mouseDrag
            (\Position
    posX Position
    posY ->
              let rect :: Rectangle
    rect = Position -> Position -> Dimension -> Dimension -> Rectangle
    Rectangle (Position -> Position
    forall a b. (Integral a, Num b) => a -> b
    fi (Int -> Position
    forall a b. (Integral a, Num b) => a -> b
    fi Int
    winX Position -> Position -> Position
    forall a. Num a => a -> a -> a
    + (Position
    posX Position -> Position -> Position
    forall a. Num a => a -> a -> a
    - Int -> Position
    forall a b. (Integral a, Num b) => a -> b
    fi Int
    offsetX)))
                                   (Position -> Position
    forall a b. (Integral a, Num b) => a -> b
    fi (Int -> Position
    forall a b. (Integral a, Num b) => a -> b
    fi Int
    winY Position -> Position -> Position
    forall a. Num a => a -> a -> a
    + (Position
    posY Position -> Position -> Position
    forall a. Num a => a -> a -> a
    - Int -> Position
    forall a b. (Integral a, Num b) => a -> b
    fi Int
    offsetY)))
                                   (Int -> Dimension
    forall a b. (Integral a, Num b) => a -> b
    fi Int
    winWidth)
                                   (Int -> Dimension
    forall a b. (Integral a, Num b) => a -> b
    fi Int
    winHeight)
              in  DraggingVisualizerMsg -> X ()
    forall a. Message a => a -> X ()
    sendMessage (DraggingVisualizerMsg -> X ()) -> DraggingVisualizerMsg -> X ()
    forall a b. (a -> b) -> a -> b
    $ Window -> Rectangle -> DraggingVisualizerMsg
    DraggingWindow Window
    window Rectangle
    rect
            )
            (DraggingVisualizerMsg -> X ()
    forall a. Message a => a -> X ()
    sendMessage DraggingVisualizerMsg
    DraggingStopped X () -> X () -> X ()
    forall a b. X a -> X b -> X b
    forall (m :: * -> *) a b. Monad m => m a -> m b -> m b
    >> Window -> X ()
    performWindowSwitching Window
    window)

    -- | get the pointer offset relative to the given windows root coordinates
    getPointerOffset :: Window -> X (Int, Int)
    getPointerOffset :: Window -> X (Int, Int)
    getPointerOffset Window
    win = do
        (Bool
    _, Window
    _, Window
    _, CInt
    oX, CInt
    oY, CInt
    _, CInt
    _, Modifier
    _) <- (Display
     -> X (Bool, Window, Window, CInt, CInt, CInt, CInt, Modifier))
    -> X (Bool, Window, Window, CInt, CInt, CInt, CInt, Modifier)
    forall a. (Display -> X a) -> X a
    withDisplay (\Display
    d -> IO (Bool, Window, Window, CInt, CInt, CInt, CInt, Modifier)
    -> X (Bool, Window, Window, CInt, CInt, CInt, CInt, Modifier)
    forall (m :: * -> *) a. MonadIO m => IO a -> m a
    io (IO (Bool, Window, Window, CInt, CInt, CInt, CInt, Modifier)
     -> X (Bool, Window, Window, CInt, CInt, CInt, CInt, Modifier))
    -> IO (Bool, Window, Window, CInt, CInt, CInt, CInt, Modifier)
    -> X (Bool, Window, Window, CInt, CInt, CInt, CInt, Modifier)
    forall a b. (a -> b) -> a -> b
    $ Display
    -> Window
    -> IO (Bool, Window, Window, CInt, CInt, CInt, CInt, Modifier)
    queryPointer Display
    d Window
    win)
        (Int, Int) -> X (Int, Int)
    forall a. a -> X a
    forall (m :: * -> *) a. Monad m => a -> m a
    return (CInt -> Int
    forall a b. (Integral a, Num b) => a -> b
    fi CInt
    oX, CInt -> Int
    forall a b. (Integral a, Num b) => a -> b
    fi CInt
    oY)

    -- | return a tuple of windowX, windowY, windowWidth, windowHeight
    getWindowPlacement :: WindowAttributes -> (Int, Int, Int, Int)
    getWindowPlacement :: WindowAttributes -> (Int, Int, Int, Int)
    getWindowPlacement WindowAttributes
    wa = (CInt -> Int
    forall a b. (Integral a, Num b) => a -> b
    fi (CInt -> Int) -> CInt -> Int
    forall a b. (a -> b) -> a -> b
    $ WindowAttributes -> CInt
    wa_x WindowAttributes
    wa, CInt -> Int
    forall a b. (Integral a, Num b) => a -> b
    fi (CInt -> Int) -> CInt -> Int
    forall a b. (a -> b) -> a -> b
    $ WindowAttributes -> CInt
    wa_y WindowAttributes
    wa, CInt -> Int
    forall a b. (Integral a, Num b) => a -> b
    fi (CInt -> Int) -> CInt -> Int
    forall a b. (a -> b) -> a -> b
    $ WindowAttributes -> CInt
    wa_width WindowAttributes
    wa, CInt -> Int
    forall a b. (Integral a, Num b) => a -> b
    fi (CInt -> Int) -> CInt -> Int
    forall a b. (a -> b) -> a -> b
    $ WindowAttributes -> CInt
    wa_height WindowAttributes
    wa)

    performWindowSwitching :: Window -> X ()
    performWindowSwitching :: Window -> X ()
    performWindowSwitching Window
    win = do
        Window
    root                          <- (XConf -> Window) -> X Window
    forall r (m :: * -> *) a. MonadReader r m => (r -> a) -> m a
    asks XConf -> Window
    theRoot
        (Bool
    _, Window
    _, Window
    selWin, CInt
    _, CInt
    _, CInt
    _, CInt
    _, Modifier
    _) <- (Display
     -> X (Bool, Window, Window, CInt, CInt, CInt, CInt, Modifier))
    -> X (Bool, Window, Window, CInt, CInt, CInt, CInt, Modifier)
    forall a. (Display -> X a) -> X a
    withDisplay (\Display
    d -> IO (Bool, Window, Window, CInt, CInt, CInt, CInt, Modifier)
    -> X (Bool, Window, Window, CInt, CInt, CInt, CInt, Modifier)
    forall (m :: * -> *) a. MonadIO m => IO a -> m a
    io (IO (Bool, Window, Window, CInt, CInt, CInt, CInt, Modifier)
     -> X (Bool, Window, Window, CInt, CInt, CInt, CInt, Modifier))
    -> IO (Bool, Window, Window, CInt, CInt, CInt, CInt, Modifier)
    -> X (Bool, Window, Window, CInt, CInt, CInt, CInt, Modifier)
    forall a b. (a -> b) -> a -> b
    $ Display
    -> Window
    -> IO (Bool, Window, Window, CInt, CInt, CInt, CInt, Modifier)
    queryPointer Display
    d Window
    root)
        WindowSet
    ws                            <- (XState -> WindowSet) -> X WindowSet
    forall s (m :: * -> *) a. MonadState s m => (s -> a) -> m a
    gets XState -> WindowSet
    windowset
        let allWindows :: [Window]
    allWindows = WindowSet -> [Window]
    forall i l a s sd. StackSet i l a s sd -> [a]
    W.index WindowSet
    ws
        Bool -> X () -> X ()
    forall (f :: * -> *). Applicative f => Bool -> f () -> f ()
    when ((Window
    win Window -> [Window] -> Bool
    forall a. Eq a => a -> [a] -> Bool
    forall (t :: * -> *) a. (Foldable t, Eq a) => a -> t a -> Bool
    `elem` [Window]
    allWindows) Bool -> Bool -> Bool
    && (Window
    selWin Window -> [Window] -> Bool
    forall a. Eq a => a -> [a] -> Bool
    forall (t :: * -> *) a. (Foldable t, Eq a) => a -> t a -> Bool
    `elem` [Window]
    allWindows)) (X () -> X ()) -> X () -> X ()
    forall a b. (a -> b) -> a -> b
    $ do
            let allWindowsSwitched :: [Window]
    allWindowsSwitched = (Window -> Window) -> [Window] -> [Window]
    forall a b. (a -> b) -> [a] -> [b]
    map (Window -> Window -> Window -> Window
    forall {a}. Eq a => a -> a -> a -> a
    switchEntries Window
    win Window
    selWin) [Window]
    allWindows
            ([Window]
    ls, Window
    t : [Window]
    rs)          <- ([Window], [Window]) -> X ([Window], [Window])
    forall a. a -> X a
    forall (f :: * -> *) a. Applicative f => a -> f a
    pure (([Window], [Window]) -> X ([Window], [Window]))
    -> ([Window], [Window]) -> X ([Window], [Window])
    forall a b. (a -> b) -> a -> b
    $ (Window -> Bool) -> [Window] -> ([Window], [Window])
    forall a. (a -> Bool) -> [a] -> ([a], [a])
    break (Window -> Window -> Bool
    forall a. Eq a => a -> a -> Bool
    == Window
    win) [Window]
    allWindowsSwitched
            let newStack :: Stack Window
    newStack           = Window -> [Window] -> [Window] -> Stack Window
    forall a. a -> [a] -> [a] -> Stack a
    W.Stack Window
    t ([Window] -> [Window]
    forall a. [a] -> [a]
    reverse [Window]
    ls) [Window]
    rs
            (WindowSet -> WindowSet) -> X ()
    windows ((WindowSet -> WindowSet) -> X ())
    -> (WindowSet -> WindowSet) -> X ()
    forall a b. (a -> b) -> a -> b
    $ (Stack Window -> Stack Window) -> WindowSet -> WindowSet
    forall a i l s sd.
    (Stack a -> Stack a) -> StackSet i l a s sd -> StackSet i l a s sd
    W.modify' ((Stack Window -> Stack Window) -> WindowSet -> WindowSet)
    -> (Stack Window -> Stack Window) -> WindowSet -> WindowSet
    forall a b. (a -> b) -> a -> b
    $ Stack Window -> Stack Window -> Stack Window
    forall a b. a -> b -> a
    const Stack Window
    newStack
       where
        switchEntries :: a -> a -> a -> a
    switchEntries a
    a a
    b a
    x | a
    x a -> a -> Bool
    forall a. Eq a => a -> a -> Bool
    == a
    a    = a
    b
                            | a
    x a -> a -> Bool
    forall a. Eq a => a -> a -> Bool
    == a
    b    = a
    a
                            | Bool
    otherwise = a
    x