mirror of
https://github.com/xmonad/xmonad-contrib.git
synced 2025-05-19 11:30:22 -07:00
This is a convenience module in order to have less import noise. It re-exports the following: a) Commonly used modules in full (Data.Foldable, Data.Applicative, and so on); though only those that play nicely with each other, so that XMonad.Prelude can be imported unqualified without any problems. This prevents things like `Prelude.(.)` and `Control.Category.(.)` fighting with each other. b) Helper functions that don't necessarily fit in any other module; e.g., the often used abbreviation `fi = fromIntegral`.
141 lines
6.3 KiB
Haskell
141 lines
6.3 KiB
Haskell
{-# LANGUAGE FlexibleInstances, MultiParamTypeClasses #-}
|
|
----------------------------------------------------------------------------
|
|
-- |
|
|
-- Module : XMonad.Layout.WindowSwitcherDecoration
|
|
-- Copyright : (c) Jan Vornberger 2009
|
|
-- Alejandro Serrano 2010
|
|
-- License : BSD3-style (see LICENSE)
|
|
--
|
|
-- Maintainer : jan.vornberger@informatik.uni-oldenburg.de
|
|
-- Stability : unstable
|
|
-- Portability : not portable
|
|
--
|
|
-- A decoration that allows to switch the position of windows by dragging
|
|
-- them onto each other.
|
|
--
|
|
-----------------------------------------------------------------------------
|
|
|
|
module XMonad.Layout.WindowSwitcherDecoration
|
|
( -- * Usage:
|
|
-- $usage
|
|
windowSwitcherDecoration,
|
|
windowSwitcherDecorationWithButtons,
|
|
windowSwitcherDecorationWithImageButtons,
|
|
WindowSwitcherDecoration, ImageWindowSwitcherDecoration,
|
|
) where
|
|
|
|
import XMonad
|
|
import XMonad.Layout.Decoration
|
|
import XMonad.Layout.DecorationAddons
|
|
import XMonad.Layout.ImageButtonDecoration
|
|
import XMonad.Layout.DraggingVisualizer
|
|
import qualified XMonad.StackSet as S
|
|
import XMonad.Prelude
|
|
import Foreign.C.Types(CInt)
|
|
|
|
-- $usage
|
|
-- You can use this module with the following in your
|
|
-- @~\/.xmonad\/xmonad.hs@:
|
|
--
|
|
-- > import XMonad.Layout.WindowSwitcherDecoration
|
|
-- > import XMonad.Layout.DraggingVisualizer
|
|
--
|
|
-- Then edit your @layoutHook@ by adding the WindowSwitcherDecoration to
|
|
-- your layout:
|
|
--
|
|
-- > myL = windowSwitcherDecoration shrinkText def (draggingVisualizer $ layoutHook def)
|
|
-- > main = xmonad def { layoutHook = myL }
|
|
--
|
|
-- There is also a version of the decoration that contains buttons like
|
|
-- "XMonad.Layout.ButtonDecoration". To use that version, you will need to
|
|
-- import "XMonad.Layout.DecorationAddons" as well and modify your @layoutHook@
|
|
-- in the following way:
|
|
--
|
|
-- > import XMonad.Layout.DecorationAddons
|
|
-- >
|
|
-- > myL = windowSwitcherDecorationWithButtons shrinkText defaultThemeWithButtons (draggingVisualizer $ layoutHook def)
|
|
-- > main = xmonad def { layoutHook = myL }
|
|
--
|
|
-- Additionaly, there is a version of the decoration that contains image buttons like
|
|
-- "XMonad.Layout.ImageButtonDecoration". To use that version, you will need to
|
|
-- import "XMonad.Layout.ImageButtonDecoration" as well and modify your @layoutHook@
|
|
-- in the following way:
|
|
--
|
|
-- > import XMonad.Layout.ImageButtonDecoration
|
|
-- >
|
|
-- > myL = windowSwitcherDecorationWithImageButtons shrinkText defaultThemeWithImageButtons (draggingVisualizer $ layoutHook def)
|
|
-- > main = xmonad def { layoutHook = myL }
|
|
--
|
|
|
|
windowSwitcherDecoration :: (Eq a, Shrinker s) => s -> Theme
|
|
-> l a -> ModifiedLayout (Decoration WindowSwitcherDecoration s) l a
|
|
windowSwitcherDecoration s c = decoration s c $ WSD False
|
|
|
|
windowSwitcherDecorationWithButtons :: (Eq a, Shrinker s) => s -> Theme
|
|
-> l a -> ModifiedLayout (Decoration WindowSwitcherDecoration s) l a
|
|
windowSwitcherDecorationWithButtons s c = decoration s c $ WSD True
|
|
|
|
data WindowSwitcherDecoration a = WSD Bool deriving (Show, Read)
|
|
|
|
instance Eq a => DecorationStyle WindowSwitcherDecoration a where
|
|
describeDeco _ = "WindowSwitcherDeco"
|
|
|
|
decorationCatchClicksHook (WSD withButtons) mainw dFL dFR = if withButtons
|
|
then titleBarButtonHandler mainw dFL dFR
|
|
else return False
|
|
decorationWhileDraggingHook _ ex ey (mainw, r) x y = handleTiledDraggingInProgress ex ey (mainw, r) x y
|
|
decorationAfterDraggingHook _ (mainw, _) decoWin = do focus mainw
|
|
hasCrossed <- handleScreenCrossing mainw decoWin
|
|
unless hasCrossed $ do sendMessage $ DraggingStopped
|
|
performWindowSwitching mainw
|
|
|
|
-- Note: the image button code is duplicated from the above
|
|
-- because the title bar handle is different
|
|
|
|
windowSwitcherDecorationWithImageButtons :: (Eq a, Shrinker s) => s -> Theme
|
|
-> l a -> ModifiedLayout (Decoration ImageWindowSwitcherDecoration s) l a
|
|
windowSwitcherDecorationWithImageButtons s c = decoration s c $ IWSD True
|
|
|
|
data ImageWindowSwitcherDecoration a = IWSD Bool deriving (Show, Read)
|
|
|
|
instance Eq a => DecorationStyle ImageWindowSwitcherDecoration a where
|
|
describeDeco _ = "ImageWindowSwitcherDeco"
|
|
|
|
decorationCatchClicksHook (IWSD withButtons) mainw dFL dFR = if withButtons
|
|
then imageTitleBarButtonHandler mainw dFL dFR
|
|
else return False
|
|
decorationWhileDraggingHook _ ex ey (mainw, r) x y = handleTiledDraggingInProgress ex ey (mainw, r) x y
|
|
decorationAfterDraggingHook _ (mainw, _) decoWin = do focus mainw
|
|
hasCrossed <- handleScreenCrossing mainw decoWin
|
|
unless hasCrossed $ do sendMessage $ DraggingStopped
|
|
performWindowSwitching mainw
|
|
|
|
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 = S.index ws
|
|
-- do a little double check to be sure
|
|
if (win `elem` allWindows) && (selWin `elem` allWindows)
|
|
then do
|
|
let allWindowsSwitched = map (switchEntries win selWin) allWindows
|
|
let (ls, t:rs) = break (win ==) allWindowsSwitched
|
|
let newStack = S.Stack t (reverse ls) rs
|
|
windows $ S.modify' $ \_ -> newStack
|
|
else return ()
|
|
where
|
|
switchEntries a b x
|
|
| x == a = b
|
|
| x == b = a
|
|
| otherwise = x
|