mirror of
https://github.com/xmonad/xmonad-contrib.git
synced 2025-05-19 11:30:22 -07:00
Implement proper handling of dynamically changing hostname
The module implements a proper way of finding out whether the window is remote or local. Just checking for a hostname and WM_CLIENT_MACHINE being equal is often not enough because the hostname is a changing subject (without any established notification mechanisms), and thus WM_CLIENT_MACHINE and the hostname can diverge even for a local window. This module solves the problem. As soon as there is a new window created, we check the hostname and WM_CLIENT_MACHINE, and then we cache the result into the XMONAD_REMOTE property. Notice that XMonad itself does not know anything about hostnames, nor does it have any dependency on Network.* modules. For this module it is not a problem: you can provide a mean to get the hostname through your config file (see usage). Or, if you don't like the hassle of handling dynamic hostnames (suppose your hostname never changes), it is also fine: this module will fallback to using environment variables.
This commit is contained in:
parent
b2a885fe5a
commit
27f4d5dafe
@ -46,10 +46,10 @@ module XMonad.Layout.Stoppable
|
|||||||
import XMonad
|
import XMonad
|
||||||
import XMonad.Actions.WithAll
|
import XMonad.Actions.WithAll
|
||||||
import XMonad.Util.WindowProperties
|
import XMonad.Util.WindowProperties
|
||||||
|
import XMonad.Util.RemoteWindows
|
||||||
import XMonad.Util.Timer
|
import XMonad.Util.Timer
|
||||||
import XMonad.StackSet hiding (filter)
|
import XMonad.StackSet hiding (filter)
|
||||||
import XMonad.Layout.LayoutModifier
|
import XMonad.Layout.LayoutModifier
|
||||||
import System.Posix.Env
|
|
||||||
import System.Posix.Signals
|
import System.Posix.Signals
|
||||||
import Data.Maybe
|
import Data.Maybe
|
||||||
import Control.Monad
|
import Control.Monad
|
||||||
@ -67,8 +67,10 @@ import Control.Monad
|
|||||||
-- proccesses, which means that it needs to know the hostname, so it looks
|
-- proccesses, which means that it needs to know the hostname, so it looks
|
||||||
-- for environment variables (e.g. HOST).
|
-- for environment variables (e.g. HOST).
|
||||||
--
|
--
|
||||||
-- Beware that as of now this module does not support dynamically changing
|
-- Environment variables will work for most cases, but won't work if the
|
||||||
-- hostnames.
|
-- hostname changes. To cover dynamic hostnames case, in addition to
|
||||||
|
-- layoutHook you have to provide manageHook from
|
||||||
|
-- "XMonad.Util.RemoteWindows" module.
|
||||||
--
|
--
|
||||||
-- For more detailed instructions on editing the layoutHook see:
|
-- For more detailed instructions on editing the layoutHook see:
|
||||||
--
|
--
|
||||||
@ -80,12 +82,7 @@ signalWindow s w = do
|
|||||||
io $ (signalProcess s . fromIntegral) `mapM_` fromMaybe [] pid
|
io $ (signalProcess s . fromIntegral) `mapM_` fromMaybe [] pid
|
||||||
|
|
||||||
signalLocalWindow :: Signal -> Window -> X ()
|
signalLocalWindow :: Signal -> Window -> X ()
|
||||||
signalLocalWindow s w = do
|
signalLocalWindow s w = isLocalWindow w >>= flip when (signalWindow s w)
|
||||||
host <- io $ pickOneMaybe `liftM` (getEnv `mapM` vars)
|
|
||||||
hasProperty (Machine host) w >>= flip when (signalWindow s w)
|
|
||||||
where
|
|
||||||
pickOneMaybe = last . (mzero:) . take 1 . catMaybes
|
|
||||||
vars = ["XAUTHLOCALHOSTNAME","HOST","HOSTNAME"]
|
|
||||||
|
|
||||||
withAllOn :: (a -> X ()) -> Workspace i l a -> X ()
|
withAllOn :: (a -> X ()) -> Workspace i l a -> X ()
|
||||||
withAllOn f wspc = f `mapM_` integrate' (stack wspc)
|
withAllOn f wspc = f `mapM_` integrate' (stack wspc)
|
||||||
|
90
XMonad/Util/RemoteWindows.hs
Normal file
90
XMonad/Util/RemoteWindows.hs
Normal file
@ -0,0 +1,90 @@
|
|||||||
|
-----------------------------------------------------------------------------
|
||||||
|
-- |
|
||||||
|
-- Module : XMonad.Util.RemoteWindows
|
||||||
|
-- Copyright : (c) Anton Vorontsov <anton@enomsg.org> 2014
|
||||||
|
-- License : BSD-style (as xmonad)
|
||||||
|
--
|
||||||
|
-- Maintainer : Anton Vorontsov <anton@enomsg.org>
|
||||||
|
-- Stability : unstable
|
||||||
|
-- Portability : unportable
|
||||||
|
--
|
||||||
|
-- This module implements a proper way of finding out whether the window
|
||||||
|
-- is remote or local.
|
||||||
|
--
|
||||||
|
-- Just checking for a hostname and WM_CLIENT_MACHINE being equal is often
|
||||||
|
-- not enough because the hostname is a changing subject (without any
|
||||||
|
-- established notification mechanisms), and thus WM_CLIENT_MACHINE and
|
||||||
|
-- the hostname can diverge even for a local window.
|
||||||
|
--
|
||||||
|
-- This module solves the problem. As soon as there is a new window
|
||||||
|
-- created, we check the hostname and WM_CLIENT_MACHINE, and then we cache
|
||||||
|
-- the result into the XMONAD_REMOTE property.
|
||||||
|
--
|
||||||
|
-- Notice that XMonad itself does not know anything about hostnames, nor
|
||||||
|
-- does it have any dependency on Network.* modules. For this module it is
|
||||||
|
-- not a problem: you can provide a mean to get the hostname through your
|
||||||
|
-- config file (see usage). Or, if you don't like the hassle of handling
|
||||||
|
-- dynamic hostnames (suppose your hostname never changes), it is also
|
||||||
|
-- fine: this module will fallback to using environment variables.
|
||||||
|
--
|
||||||
|
-----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
module XMonad.Util.RemoteWindows
|
||||||
|
( -- $usage
|
||||||
|
isLocalWindow
|
||||||
|
, manageRemote
|
||||||
|
, manageRemoteG
|
||||||
|
) where
|
||||||
|
|
||||||
|
import XMonad
|
||||||
|
import XMonad.Util.WindowProperties
|
||||||
|
import Data.Monoid
|
||||||
|
import Data.Maybe
|
||||||
|
import Control.Monad
|
||||||
|
import System.Posix.Env
|
||||||
|
|
||||||
|
-- $usage
|
||||||
|
-- You can use this module with the following in your @~\/.xmonad\/xmonad.hs@:
|
||||||
|
--
|
||||||
|
-- > import XMonad
|
||||||
|
-- > import XMonad.Util.RemoteWindows
|
||||||
|
-- > import Network.BSD
|
||||||
|
-- >
|
||||||
|
-- > main = xmonad def
|
||||||
|
-- > { manageHook = manageRemote =<< io getHostName }
|
||||||
|
|
||||||
|
guessHostName :: IO String
|
||||||
|
guessHostName = pickOneMaybe `liftM` (getEnv `mapM` vars)
|
||||||
|
where
|
||||||
|
pickOneMaybe = last . (mzero:) . take 1 . catMaybes
|
||||||
|
vars = ["XAUTHLOCALHOSTNAME","HOST","HOSTNAME"]
|
||||||
|
|
||||||
|
setRemoteProp :: Window -> String -> X ()
|
||||||
|
setRemoteProp w host = do
|
||||||
|
d <- asks display
|
||||||
|
p <- getAtom "XMONAD_REMOTE"
|
||||||
|
t <- getAtom "CARDINAL"
|
||||||
|
v <- hasProperty (Machine host) w
|
||||||
|
io $ changeProperty32 d w p t propModeReplace
|
||||||
|
[fromIntegral . fromEnum $ not v]
|
||||||
|
|
||||||
|
-- | Given a window, tell if it is a local or a remote process. Normally,
|
||||||
|
-- it checks XMONAD_REMOTE property. If it does not exist (i.e. the
|
||||||
|
-- manageRemote hook was not deployed in user's config), it falls back to
|
||||||
|
-- checking environment variables and assuming that hostname never
|
||||||
|
-- changes.
|
||||||
|
isLocalWindow :: Window -> X Bool
|
||||||
|
isLocalWindow w = getProp32s "XMONAD_REMOTE" w >>= \p -> case p of
|
||||||
|
Just [y] -> return $ y == 0
|
||||||
|
_ -> io guessHostName >>= \host -> hasProperty (Machine host) w
|
||||||
|
|
||||||
|
-- | Use this hook to let XMonad properly track remote/local windows. For
|
||||||
|
-- example, @manageHook = manageRemote =<< io getHostName@.
|
||||||
|
manageRemote :: String -> ManageHook
|
||||||
|
manageRemote host = ask >>= \w -> liftX (setRemoteProp w host) >> return mempty
|
||||||
|
|
||||||
|
-- | Use this hook if you want to manage XMONAD_REMOTE properties, but
|
||||||
|
-- don't want to use an external getHostName in your config. That way you
|
||||||
|
-- are retreating to environment variables.
|
||||||
|
manageRemoteG :: ManageHook
|
||||||
|
manageRemoteG = manageRemote =<< io guessHostName
|
@ -307,6 +307,7 @@ library
|
|||||||
XMonad.Util.NamedWindows
|
XMonad.Util.NamedWindows
|
||||||
XMonad.Util.Paste
|
XMonad.Util.Paste
|
||||||
XMonad.Util.PositionStore
|
XMonad.Util.PositionStore
|
||||||
|
XMonad.Util.RemoteWindows
|
||||||
XMonad.Util.Replace
|
XMonad.Util.Replace
|
||||||
XMonad.Util.Run
|
XMonad.Util.Run
|
||||||
XMonad.Util.Scratchpad
|
XMonad.Util.Scratchpad
|
||||||
|
Loading…
x
Reference in New Issue
Block a user