XMonad.Hooks.RefocusLast

xmonad-contrib-0.18.1: Community-maintained extensions for xmonad

Copyright | (c) 2018 L. S. Leary
License | BSD3-style (see LICENSE)
Maintainer | L. S. Leary
Stability | unstable
Portability | unportable
Safe Haskell | None
Language | Haskell2010

XMonad.Hooks.RefocusLast

Contents

- Usage
  - Predicates
- Actions
- Types
- Library functions

Description

Provides hooks and actions that keep track of recently focused windows on a per workspace basis and automatically refocus the last window on loss of the current (if appropriate as determined by user specified criteria).

Synopsis

- refocusLastLogHook :: X ()
- refocusLastLayoutHook :: l a -> ModifiedLayout RefocusLastLayoutHook l a
- refocusLastWhen :: Query Bool -> Event -> X All
- refocusingIsActive :: Query Bool
- isFloat :: Query Bool
- toggleRefocusing :: X ()
- toggleFocus :: X ()
- swapWithLast :: X ()
- refocusWhen :: Query Bool -> WorkspaceId -> X (WindowSet -> WindowSet)
- shiftRLWhen :: Query Bool -> WorkspaceId -> X (WindowSet -> WindowSet)
- updateRecentsOn :: WorkspaceId -> X ()
- data RecentWins = Recent {
  - previous :: !Window
  - current :: !Window
  }
- newtype RecentsMap = RecentsMap (Map WorkspaceId RecentWins)
- data RefocusLastLayoutHook a = RefocusLastLayoutHook
- newtype RefocusLastToggle = RefocusLastToggle {
  - refocusing :: Bool
  }
- withRecentsIn :: WorkspaceId -> a -> (Window -> Window -> X a) -> X a

# Usage

To use this module, you must either include `refocusLastLogHook` in your log hook or `refocusLastLayoutHook` in your layout hook; don't use both. This suffices to make use of both `toggleFocus` and `shiftRLWhen` but will not refocus automatically upon loss of the current window; for that you must include in your event hook ``refocusLastWhen` pred` for some valid `pred`.

The event hooks that trigger refocusing only fire when a window is lost completely, not when it's simply e.g. moved to another workspace. Hence you will need to use ``shiftRLWhen` pred` or ``refocusWhen` pred` as appropriate if you want the same behaviour in such cases.

Example configuration:

    import XMonad
    import XMonad.Hooks.RefocusLast
    import qualified Data.Map.Strict as M

    main :: IO ()
    main = xmonad def
        { handleEventHook = refocusLastWhen myPred <> handleEventHook def
        , logHook         = refocusLastLogHook     <> logHook         def
    --  , layoutHook      = refocusLastLayoutHook   $  layoutHook      def
        , keys            = refocusLastKeys        <> keys            def
        } where
            myPred = refocusingIsActive <||> isFloat
            refocusLastKeys cnf
              = M.fromList
              $ ((modMask cnf              , xK_a), toggleFocus)
              : ((modMask cnf .|. shiftMask, xK_a), swapWithLast)
              : ((modMask cnf              , xK_b), toggleRefocusing)
              : [ ( (modMask cnf .|. shiftMask, n)
                  , windows =<< shiftRLWhen myPred wksp
                  )
                | (n, wksp) <- zip [xK_1..xK_9] (workspaces cnf)
                ]

refocusLastLogHook :: X () #

A log hook recording the current workspace's most recently focused windows into extensible state.

refocusLastLayoutHook :: l a -> ModifiedLayout RefocusLastLayoutHook l a #

Records a workspace's recently focused windows into extensible state upon relayout. Potentially a less wasteful alternative to `refocusLastLogHook`, as it does not run on `WM_NAME` `propertyNotify` events.

refocusLastWhen :: Query Bool -> Event -> X All #

Given a predicate on the event window determining whether or not to act, construct an event hook that runs iff the core xmonad event handler will unmanage the window, and which shifts focus to the last focused window on the appropriate workspace if desired.

## Predicates

Impure `Query Bool` predicates on event windows for use as arguments to `refocusLastWhen`, `shiftRLWhen` and `refocusWhen`. Can be combined with `<||>` or `<&&>`. Use like e.g.

    , handleEventHook = refocusLastWhen refocusingIsActive

or in a keybinding:

    windows =<< shiftRLWhen (refocusingIsActive <&&> isFloat) "3"

It's also valid to use a property lookup like `className =? "someProgram"` as a predicate, and it should function as expected with e.g. `shiftRLWhen`. In the event hook on the other hand, the window in question has already been unmapped or destroyed, so external lookups to X properties don't work: only the information fossilised in xmonad's state is available.

refocusingIsActive :: Query Bool #

Holds iff refocusing is toggled active.

isFloat :: Query Bool #

Holds iff the event window is a float.

# Actions

toggleRefocusing :: X () #

Toggle automatic refocusing at runtime. Has no effect unless the `refocusingIsActive` predicate has been used.

toggleFocus :: X () #

Refocuses the previously focused window; acts as a toggle. Is not affected by `toggleRefocusing`.

swapWithLast :: X () #

Swaps the current and previous windows of the current workspace. Is not affected by `toggleRefocusing`.

refocusWhen :: Query Bool -> WorkspaceId -> X (WindowSet -> WindowSet) #

Given a target workspace and a predicate on its current window, produce a `windows` suitable function that will refocus that workspace appropriately. Allows you to hook refocusing into any action you can run through `windows`. See the implementation of `shiftRLWhen` for a straight-forward usage example.

shiftRLWhen :: Query Bool -> WorkspaceId -> X (WindowSet -> WindowSet) #

Sends the focused window to the specified workspace, refocusing the last focused window if the predicate holds on the current window. Note that the native version of this, `windows . W.shift`, has a nice property that this does not: shifting a window to another workspace then shifting it back preserves its place in the stack. Can be used in a keybinding like e.g.

    windows =<< shiftRLWhen refocusingIsActive "3"

or

    (windows <=< shiftRLWhen refocusingIsActive) "3"

where `<=<` is imported from Control.Monad.

updateRecentsOn :: WorkspaceId -> X () #

Perform an update to the `RecentWins` for the specified workspace. The RefocusLast log and layout hooks are both implemented trivially in terms of this function. Only exported to aid extensibility.

# Types

The types and constructors used in this module are exported principally to aid extensibility; typical users will have nothing to gain from this section.

data RecentWins #

Data type holding onto the previous and current `Window`.

Constructors

Recent |
Fields previous :: !Window current :: !Window

#### Instances

Instances details

Read RecentWins # |
Instance details Defined in XMonad.Hooks.RefocusLast Methods readsPrec :: Int -> ReadS RecentWins # readList :: ReadS [RecentWins] # readPrec :: ReadPrec RecentWins # readListPrec :: ReadPrec [RecentWins] #
Show RecentWins # |
Instance details Defined in XMonad.Hooks.RefocusLast Methods showsPrec :: Int -> RecentWins -> ShowS # show :: RecentWins -> String # showList :: [RecentWins] -> ShowS #
Eq RecentWins # |
Instance details Defined in XMonad.Hooks.RefocusLast Methods (==) :: RecentWins -> RecentWins -> Bool # (/=) :: RecentWins -> RecentWins -> Bool #

newtype RecentsMap #

Newtype wrapper for a `Map` holding the `RecentWins` for each workspace. Is an instance of `ExtensionClass` with persistence of state.

Constructors

RecentsMap (Map WorkspaceId RecentWins) |

#### Instances

Instances details

Read RecentsMap # |
Instance details Defined in XMonad.Hooks.RefocusLast Methods readsPrec :: Int -> ReadS RecentsMap # readList :: ReadS [RecentsMap] # readPrec :: ReadPrec RecentsMap # readListPrec :: ReadPrec [RecentsMap] #
Show RecentsMap # |
Instance details Defined in XMonad.Hooks.RefocusLast Methods showsPrec :: Int -> RecentsMap -> ShowS # show :: RecentsMap -> String # showList :: [RecentsMap] -> ShowS #
Eq RecentsMap # |
Instance details Defined in XMonad.Hooks.RefocusLast Methods (==) :: RecentsMap -> RecentsMap -> Bool # (/=) :: RecentsMap -> RecentsMap -> Bool #
ExtensionClass RecentsMap # |
Instance details Defined in XMonad.Hooks.RefocusLast Methods initialValue :: RecentsMap # extensionType :: RecentsMap -> StateExtension #

data RefocusLastLayoutHook a #

A `LayoutModifier` that updates the `RecentWins` for a workspace upon relayout.

Constructors

RefocusLastLayoutHook |

#### Instances

Instances details

LayoutModifier RefocusLastLayoutHook a # |
Instance details Defined in XMonad.Hooks.RefocusLast Methods modifyLayout :: LayoutClass l a => RefocusLastLayoutHook a -> Workspace WorkspaceId (l a) a -> Rectangle -> X ([(a, Rectangle)], Maybe (l a)) # modifyLayoutWithUpdate :: LayoutClass l a => RefocusLastLayoutHook a -> Workspace WorkspaceId (l a) a -> Rectangle -> X (([(a, Rectangle)], Maybe (l a)), Maybe (RefocusLastLayoutHook a)) # handleMess :: RefocusLastLayoutHook a -> SomeMessage -> X (Maybe (RefocusLastLayoutHook a)) # handleMessOrMaybeModifyIt :: RefocusLastLayoutHook a -> SomeMessage -> X (Maybe (Either (RefocusLastLayoutHook a) SomeMessage)) # pureMess :: RefocusLastLayoutHook a -> SomeMessage -> Maybe (RefocusLastLayoutHook a) # redoLayout :: RefocusLastLayoutHook a -> Rectangle -> Maybe (Stack a) -> [(a, Rectangle)] -> X ([(a, Rectangle)], Maybe (RefocusLastLayoutHook a)) # pureModifier :: RefocusLastLayoutHook a -> Rectangle -> Maybe (Stack a) -> [(a, Rectangle)] -> ([(a, Rectangle)], Maybe (RefocusLastLayoutHook a)) # hook :: RefocusLastLayoutHook a -> X () # unhook :: RefocusLastLayoutHook a -> X () # modifierDescription :: RefocusLastLayoutHook a -> String # modifyDescription :: LayoutClass l a => RefocusLastLayoutHook a -> l a -> String #
Read (RefocusLastLayoutHook a) # |
Instance details Defined in XMonad.Hooks.RefocusLast Methods readsPrec :: Int -> ReadS (RefocusLastLayoutHook a) # readList :: ReadS [RefocusLastLayoutHook a] # readPrec :: ReadPrec (RefocusLastLayoutHook a) # readListPrec :: ReadPrec [RefocusLastLayoutHook a] #
Show (RefocusLastLayoutHook a) # |
Instance details Defined in XMonad.Hooks.RefocusLast Methods showsPrec :: Int -> RefocusLastLayoutHook a -> ShowS # show :: RefocusLastLayoutHook a -> String # showList :: [RefocusLastLayoutHook a] -> ShowS #

newtype RefocusLastToggle #

A newtype on `Bool` to act as a universal toggle for refocusing.

Constructors

RefocusLastToggle |
Fields refocusing :: Bool

#### Instances

Instances details

Read RefocusLastToggle # |
Instance details Defined in XMonad.Hooks.RefocusLast Methods readsPrec :: Int -> ReadS RefocusLastToggle # readList :: ReadS [RefocusLastToggle] # readPrec :: ReadPrec RefocusLastToggle # readListPrec :: ReadPrec [RefocusLastToggle] #
Show RefocusLastToggle # |
Instance details Defined in XMonad.Hooks.RefocusLast Methods showsPrec :: Int -> RefocusLastToggle -> ShowS # show :: RefocusLastToggle -> String # showList :: [RefocusLastToggle] -> ShowS #
Eq RefocusLastToggle # |
Instance details Defined in XMonad.Hooks.RefocusLast Methods (==) :: RefocusLastToggle -> RefocusLastToggle -> Bool # (/=) :: RefocusLastToggle -> RefocusLastToggle -> Bool #
ExtensionClass RefocusLastToggle # |
Instance details Defined in XMonad.Hooks.RefocusLast Methods initialValue :: RefocusLastToggle # extensionType :: RefocusLastToggle -> StateExtension #

# Library functions

withRecentsIn :: WorkspaceId -> a -> (Window -> Window -> X a) -> X a #

Perform an X action dependent on successful lookup of the RecentWins for the specified workspace, or return a default value.