mirror of
https://github.com/elkowar/dots-of-war.git
synced 2024-11-06 03:12:24 +00:00
Cleanup implementation of tiled window dragging
This commit is contained in:
parent
3c68399280
commit
078255a414
4 changed files with 77 additions and 80 deletions
Binary file not shown.
|
@ -6,13 +6,14 @@ module Config (main) where
|
||||||
import qualified Data.Map.Strict as M
|
import qualified Data.Map.Strict as M
|
||||||
import Control.Concurrent
|
import Control.Concurrent
|
||||||
import Control.Exception ( catch , SomeException)
|
import Control.Exception ( catch , SomeException)
|
||||||
import Control.Monad ( filterM, when )
|
import Control.Monad ( filterM )
|
||||||
import Control.Arrow ( (>>>) )
|
import Control.Arrow ( (>>>) )
|
||||||
import Data.List ( isPrefixOf , isSuffixOf)
|
import Data.List ( isPrefixOf , isSuffixOf)
|
||||||
import System.Exit (exitSuccess)
|
import System.Exit (exitSuccess)
|
||||||
|
|
||||||
import qualified Rofi
|
import qualified Rofi
|
||||||
import qualified DescribedSubmap
|
import qualified DescribedSubmap
|
||||||
|
import qualified TiledDragging
|
||||||
|
|
||||||
|
|
||||||
import Data.Foldable ( for_ )
|
import Data.Foldable ( for_ )
|
||||||
|
@ -47,12 +48,10 @@ import XMonad.Layout.ThreeColumns
|
||||||
|
|
||||||
import XMonad.Layout.WindowSwitcherDecoration
|
import XMonad.Layout.WindowSwitcherDecoration
|
||||||
import XMonad.Layout.DraggingVisualizer
|
import XMonad.Layout.DraggingVisualizer
|
||||||
import XMonad.Layout.DecorationAddons
|
|
||||||
|
|
||||||
import XMonad.Util.EZConfig ( additionalKeysP
|
import XMonad.Util.EZConfig ( additionalKeysP
|
||||||
, removeKeysP
|
, removeKeysP
|
||||||
, checkKeymap
|
, checkKeymap
|
||||||
, additionalMouseBindings
|
|
||||||
)
|
)
|
||||||
import XMonad.Util.NamedScratchpad
|
import XMonad.Util.NamedScratchpad
|
||||||
import XMonad.Util.Run
|
import XMonad.Util.Run
|
||||||
|
@ -60,10 +59,6 @@ import XMonad.Util.SpawnOnce (spawnOnce)
|
||||||
import XMonad.Util.WorkspaceCompare ( getSortByXineramaPhysicalRule , getSortByIndex)
|
import XMonad.Util.WorkspaceCompare ( getSortByXineramaPhysicalRule , getSortByIndex)
|
||||||
|
|
||||||
import qualified Data.Monoid
|
import qualified Data.Monoid
|
||||||
import Data.Monoid ( All
|
|
||||||
, All(..)
|
|
||||||
)
|
|
||||||
import Data.Int ( Int32 )
|
|
||||||
import qualified System.IO as SysIO
|
import qualified System.IO as SysIO
|
||||||
import qualified XMonad.Actions.Navigation2D as Nav2d
|
import qualified XMonad.Actions.Navigation2D as Nav2d
|
||||||
import qualified XMonad.Config.Desktop as Desktop
|
import qualified XMonad.Config.Desktop as Desktop
|
||||||
|
@ -75,9 +70,7 @@ import qualified XMonad.Layout.MultiToggle.Instances as MTog
|
||||||
import qualified XMonad.Layout.ToggleLayouts as ToggleLayouts
|
import qualified XMonad.Layout.ToggleLayouts as ToggleLayouts
|
||||||
import qualified XMonad.StackSet as W
|
import qualified XMonad.StackSet as W
|
||||||
import qualified XMonad.Util.XSelection as XSel
|
import qualified XMonad.Util.XSelection as XSel
|
||||||
import XMonad.Util.XUtils ( fi )
|
|
||||||
import qualified XMonad.Layout.PerScreen as PerScreen
|
import qualified XMonad.Layout.PerScreen as PerScreen
|
||||||
import Foreign.C.Types ( CInt )
|
|
||||||
{-# ANN module "HLint: ignore Redundant $" #-}
|
{-# ANN module "HLint: ignore Redundant $" #-}
|
||||||
{-# ANN module "HLint: ignore Redundant bracket" #-}
|
{-# ANN module "HLint: ignore Redundant bracket" #-}
|
||||||
{-# ANN module "HLint: ignore Move brackets to avoid $" #-}
|
{-# ANN module "HLint: ignore Move brackets to avoid $" #-}
|
||||||
|
@ -158,11 +151,11 @@ myLayout = avoidStruts
|
||||||
$ MTog.mkToggle1 MTog.FULL
|
$ MTog.mkToggle1 MTog.FULL
|
||||||
$ ToggleLayouts.toggleLayouts (rename "Tabbed" . makeTabbed . spacingAndGaps $ ResizableTall 1 (3/100) (1/2) [])
|
$ ToggleLayouts.toggleLayouts (rename "Tabbed" . makeTabbed . spacingAndGaps $ ResizableTall 1 (3/100) (1/2) [])
|
||||||
$ MTog.mkToggle1 WINDOWDECORATION
|
$ MTog.mkToggle1 WINDOWDECORATION
|
||||||
$ draggingVisualizer
|
$ draggingVisualizer
|
||||||
$ layoutHintsToCenter
|
$ layoutHintsToCenter
|
||||||
$ layouts
|
$ layouts
|
||||||
where
|
where
|
||||||
-- | if the screen is wider than 1900px it's horizontal, so use horizontal layouts.
|
-- | if the screen is wider than 1900px it's horizontal, so use horizontal layouts.
|
||||||
-- if it's not, it's vertical, so use layouts for vertical screens.
|
-- if it's not, it's vertical, so use layouts for vertical screens.
|
||||||
layouts = PerScreen.ifWider 1900 horizScreenLayouts vertScreenLayouts
|
layouts = PerScreen.ifWider 1900 horizScreenLayouts vertScreenLayouts
|
||||||
|
|
||||||
|
@ -223,6 +216,11 @@ myStartupHook = do
|
||||||
|
|
||||||
-- Keymap --------------------------------------- {{{
|
-- Keymap --------------------------------------- {{{
|
||||||
|
|
||||||
|
myMouseBindings :: XConfig Layout -> M.Map (KeyMask, Button) (Window -> X ())
|
||||||
|
myMouseBindings (XConfig {XMonad.modMask = modMask'}) = M.fromList
|
||||||
|
[((modMask' .|. shiftMask, button1), TiledDragging.tiledDrag)]
|
||||||
|
|
||||||
|
|
||||||
multiMonitorOperation :: (WorkspaceId -> WindowSet -> WindowSet) -> ScreenId -> X ()
|
multiMonitorOperation :: (WorkspaceId -> WindowSet -> WindowSet) -> ScreenId -> X ()
|
||||||
multiMonitorOperation operation n = do
|
multiMonitorOperation operation n = do
|
||||||
monitor <- screenWorkspace n
|
monitor <- screenWorkspace n
|
||||||
|
@ -496,75 +494,6 @@ polybarPP monitor = namedScratchpadFilterOutWorkspacePP . (if useSharedWorkspace
|
||||||
|
|
||||||
-- }}}
|
-- }}}
|
||||||
|
|
||||||
|
|
||||||
-- Window dragging {{{
|
|
||||||
|
|
||||||
myMouseBindings :: XConfig Layout -> M.Map (KeyMask, Button) (Window -> X ())
|
|
||||||
myMouseBindings (XConfig {XMonad.modMask = modMask}) = M.fromList
|
|
||||||
[((modMask .|. shiftMask, button1), tiledDragging)]
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
tiledDragging :: Window -> X ()
|
|
||||||
tiledDragging window = whenX (isClient window) $ withDisplay $ \disp -> do
|
|
||||||
focus window
|
|
||||||
windows $ W.sink window
|
|
||||||
(offsetX, offsetY) <- getPointerOffset window disp
|
|
||||||
(winX, winY, winWidth, winHeight) <- io $ getWindowPlacement disp window
|
|
||||||
|
|
||||||
mouseDrag
|
|
||||||
(\posX posY -> let rect = Rectangle (fromIntegral (fromIntegral winX + (posX - fromIntegral offsetX)))
|
|
||||||
(fromIntegral (fromIntegral winY + (posY - fromIntegral offsetY)))
|
|
||||||
(fromIntegral winWidth)
|
|
||||||
(fromIntegral winHeight)
|
|
||||||
in sendMessage $ DraggingWindow window rect)
|
|
||||||
(sendMessage DraggingStopped >> performWindowSwitching window)
|
|
||||||
|
|
||||||
|
|
||||||
-- | get the pointer offset relative to the given windows root coordinates
|
|
||||||
getPointerOffset :: Window -> Display -> X (Int, Int)
|
|
||||||
getPointerOffset win disp = do
|
|
||||||
(_, _, _, offsetX, offsetY, _, _, _) <- io $ queryPointer disp win
|
|
||||||
return (fromIntegral offsetX, fromIntegral offsetY)
|
|
||||||
|
|
||||||
-- | return a tuple of windowX, windowY, windowWidth, windowHeight
|
|
||||||
getWindowPlacement :: Display -> Window -> IO (CInt, CInt, CInt, CInt)
|
|
||||||
getWindowPlacement disp window = do
|
|
||||||
windowAttributes <- getWindowAttributes disp window
|
|
||||||
return (wa_x windowAttributes, wa_y windowAttributes, wa_width windowAttributes, wa_height windowAttributes)
|
|
||||||
|
|
||||||
|
|
||||||
handleTiledDraggingInProgress :: CInt -> CInt -> (Window, Rectangle) -> Position -> Position -> X ()
|
|
||||||
handleTiledDraggingInProgress ex ey (mainw, r) x y = do
|
|
||||||
let rect = Rectangle (x - (fi ex - rect_x r))
|
|
||||||
(y - (fi ey - rect_y r))
|
|
||||||
(rect_width r)
|
|
||||||
(rect_height r)
|
|
||||||
sendMessage $ DraggingWindow mainw rect
|
|
||||||
|
|
||||||
performWindowSwitching :: Window -> X ()
|
|
||||||
performWindowSwitching win =
|
|
||||||
withDisplay $ \d -> do
|
|
||||||
root <- asks theRoot
|
|
||||||
(_, _, selWin, _, _, _, _, _) <- io $ queryPointer d root
|
|
||||||
ws <- gets windowset
|
|
||||||
let allWindows = W.index ws
|
|
||||||
when ((win `elem` allWindows) && (selWin `elem` allWindows)) $ do
|
|
||||||
let allWindowsSwitched = map (switchEntries win selWin) allWindows
|
|
||||||
let (ls, t:rs) = break (== win) allWindowsSwitched
|
|
||||||
let newStack = W.Stack t (reverse ls) rs
|
|
||||||
windows $ W.modify' $ const newStack
|
|
||||||
where
|
|
||||||
switchEntries a b x
|
|
||||||
| x == a = b
|
|
||||||
| x == b = a
|
|
||||||
| otherwise = x
|
|
||||||
|
|
||||||
|
|
||||||
--}}}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
-- Utilities --------------------------------------------------- {{{
|
-- Utilities --------------------------------------------------- {{{
|
||||||
|
|
||||||
(|>) :: a -> (a -> b) -> b
|
(|>) :: a -> (a -> b) -> b
|
||||||
|
|
67
files/.xmonad/lib/TiledDragging.hs
Normal file
67
files/.xmonad/lib/TiledDragging.hs
Normal file
|
@ -0,0 +1,67 @@
|
||||||
|
module TiledDragging
|
||||||
|
( tiledDrag
|
||||||
|
)
|
||||||
|
where
|
||||||
|
import XMonad
|
||||||
|
|
||||||
|
import qualified XMonad.StackSet as W
|
||||||
|
import XMonad.Layout.DraggingVisualizer
|
||||||
|
import Control.Monad
|
||||||
|
|
||||||
|
|
||||||
|
-- | put this as a mouse mapping to be able to drag windows in tiled mode.
|
||||||
|
-- you need DraggingVisualizer for this to look good.
|
||||||
|
tiledDrag :: Window -> X ()
|
||||||
|
tiledDrag window = whenX (isClient window) $ do
|
||||||
|
focus window
|
||||||
|
(offsetX, offsetY) <- getPointerOffset window
|
||||||
|
(winX, winY, winWidth, winHeight) <- getWindowPlacement window
|
||||||
|
|
||||||
|
mouseDrag
|
||||||
|
(\posX posY ->
|
||||||
|
let rect = Rectangle (fInt (fInt winX + (posX - fInt offsetX)))
|
||||||
|
(fInt (fInt winY + (posY - fInt offsetY)))
|
||||||
|
(fInt winWidth)
|
||||||
|
(fInt winHeight)
|
||||||
|
in sendMessage $ DraggingWindow window rect
|
||||||
|
)
|
||||||
|
(sendMessage DraggingStopped >> performWindowSwitching window)
|
||||||
|
|
||||||
|
|
||||||
|
-- | get the pointer offset relative to the given windows root coordinates
|
||||||
|
getPointerOffset :: Window -> X (Int, Int)
|
||||||
|
getPointerOffset win = do
|
||||||
|
(_, _, _, oX, oY, _, _, _) <- withDisplay (\d -> io $ queryPointer d win)
|
||||||
|
return (fInt oX, fInt oY)
|
||||||
|
|
||||||
|
-- | return a tuple of windowX, windowY, windowWidth, windowHeight
|
||||||
|
getWindowPlacement :: Window -> X (Int, Int, Int, Int)
|
||||||
|
getWindowPlacement window = do
|
||||||
|
wa <- withDisplay (\d -> io $ getWindowAttributes d window)
|
||||||
|
return
|
||||||
|
(fInt $ wa_x wa, fInt $ wa_y wa, fInt $ wa_width wa, fInt $ wa_height wa)
|
||||||
|
|
||||||
|
|
||||||
|
performWindowSwitching :: Window -> X ()
|
||||||
|
performWindowSwitching win = do
|
||||||
|
root <- asks theRoot
|
||||||
|
(_, _, selWin, _, _, _, _, _) <- withDisplay (\d -> io $ queryPointer d root)
|
||||||
|
ws <- gets windowset
|
||||||
|
let allWindows = W.index ws
|
||||||
|
when ((win `elem` allWindows) && (selWin `elem` allWindows)) $ do
|
||||||
|
let allWindowsSwitched = map (switchEntries win selWin) allWindows
|
||||||
|
let (ls, t : rs) = break (== win) allWindowsSwitched
|
||||||
|
let newStack = W.Stack t (reverse ls) rs
|
||||||
|
windows $ W.modify' $ const newStack
|
||||||
|
where
|
||||||
|
switchEntries a b x | x == a = b
|
||||||
|
| x == b = a
|
||||||
|
| otherwise = x
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
-- | shorthand for fromIntegral
|
||||||
|
fInt :: Integral a => Integral b => a -> b
|
||||||
|
fInt = fromIntegral
|
||||||
|
|
||||||
|
|
|
@ -10,6 +10,7 @@ executable my-xmonad
|
||||||
Config
|
Config
|
||||||
Rofi
|
Rofi
|
||||||
DescribedSubmap
|
DescribedSubmap
|
||||||
|
TiledDragging
|
||||||
|
|
||||||
default-language: Haskell2010
|
default-language: Haskell2010
|
||||||
ghc-options: -Wall -threaded -fno-warn-missing-signatures
|
ghc-options: -Wall -threaded -fno-warn-missing-signatures
|
||||||
|
|
Loading…
Reference in a new issue