{-# LANGUAGE MultiParamTypeClasses, TypeSynonymInstances #-} {- | Module : XMonad.Layout.TrackFloating Description : Let focused tiles track focused floats Copyright : (c) 2010 & 2013 Adam Vogt 2011 Willem Vanlint License : BSD-style (see xmonad/LICENSE) Maintainer : vogt.adam@gmail.com Stability : unstable Portability : unportable Provides layout modifier 'UseTransientFor': when a float has focus and is @WM_TRANSIENT_FOR@ a tile, run the underlying layout as if that tile had focus. -} module XMonad.Layout.TrackFloating (-- * Usage -- $usage -- ** For other layout modifiers -- $layoutModifier trackFloating, useTransientFor, -- ** Exported types TrackFloating, UseTransientFor, ) where import XMonad.Prelude import XMonad import XMonad.Layout.LayoutModifier import XMonad.Layout.FocusTracking import XMonad.Util.Stack (findZ) import qualified XMonad.StackSet as W import qualified Data.Traversable as T {-# DEPRECATED TrackFloating "Use X.L.FocusTracking.FocusTracking." #-} type TrackFloating = FocusTracking {- | When focus is on the tiled layer, the underlying layout is run with focus on the window named by the WM_TRANSIENT_FOR property on the floating window. -} useTransientFor :: l a -> ModifiedLayout UseTransientFor l a useTransientFor = ModifiedLayout UseTransientFor data UseTransientFor a = UseTransientFor deriving (Read,Show,Eq) instance LayoutModifier UseTransientFor Window where modifyLayout _ ws@W.Workspace{ W.stack = ms } r = do m <- gets (W.peek . W.view (W.tag ws) . windowset) d <- asks display parent <- join <$> T.traverse (io . getTransientForHint d) m s0 <- get whenJust parent $ \p -> put s0{ windowset = W.focusWindow p (windowset s0) } result <- runLayout ws{ W.stack = (parent >>= \p -> findZ (p==) ms) <|> ms } r m' <- gets (W.peek . windowset) when (m' == parent) $ -- layout changed the windowset, so don't clobber it whenJust m $ \p -> put s0{ windowset = W.focusWindow p (windowset s0) } return result {- $usage Apply to your layout in a config like: > main = xmonad (def{ > layoutHook = trackFloating (useTransientFor > (noBorders Full ||| Tall 1 0.3 0.5)), > ... > }) 'useTransientFor' and 'trackFloating' can be enabled independently. For example when the floating window sets @WM_TRANSIENT_FOR@, such as libreoffice's file->preferences window, @optionA@ will have the last-focused window magnified while @optionB@ will result magnify the window that opened the preferences window regardless of which tiled window was focused before. > import XMonad.Layout.Magnifier > import XMonad.Layout.TrackFloating > > underlyingLayout = magnifier (Tall 1 0.3 0.5) > > optionA = trackFloating underlyingLayout > optionB = trackFloating (useTransientFor underlyingLayout) -} {- | Runs another layout with a remembered focus, provided: * the subset of windows doesn't include the focus in XState * it was previously run with a subset that included the XState focus * the remembered focus hasn't since been killed -} {-# DEPRECATED trackFloating "Use X.L.FocusTracking.focusTracking." #-} trackFloating :: l a -> ModifiedLayout TrackFloating l a trackFloating = focusTracking {- $layoutModifier It also corrects focus issues for full-like layouts inside other layout modifiers: > import XMonad.Layout.IM > import XMonad.Layout.Tabbed > import XMonad.Layout.TrackFloating > import XMonad.Layout.Reflect > gimpLayout = withIM 0.11 (Role "gimp-toolbox") $ reflectHoriz > $ withIM 0.15 (Role "gimp-dock") (trackFloating simpleTabbed) Interactions with some layout modifiers (ex. decorations, minimizing) are unknown but likely unpleasant. -}