xmonad-config/lib/XMonad/Internal/DBus/Control.hs

102 lines
3.1 KiB
Haskell

{-# LANGUAGE ScopedTypeVariables #-}
--------------------------------------------------------------------------------
-- High-level interface for managing XMonad's DBus
module XMonad.Internal.DBus.Control
( Client
, DBusState (..)
, withDBusX
, withDBusX_
, withDBus
, withDBus_
, connectDBus
, connectDBusX
, disconnectDBus
, disconnectDBusX
, getDBusClient
, withDBusClient
, withDBusClient_
, disconnect
, dbusExporters
)
where
import DBus
import DBus.Client
import Data.Internal.DBus
import Data.Internal.Dependency
import RIO
import XMonad.Internal.DBus.Brightness.ClevoKeyboard
import XMonad.Internal.DBus.Brightness.IntelBacklight
import XMonad.Internal.DBus.Common
import XMonad.Internal.DBus.Screensaver
-- | Current connections to the DBus (session and system buses)
data DBusState = DBusState
{ dbSesClient :: Maybe SesClient
, dbSysClient :: Maybe SysClient
}
withDBusX_ :: MonadUnliftIO m => (DBusState -> m a) -> m ()
withDBusX_ = void . withDBusX
withDBusX :: MonadUnliftIO m => (DBusState -> m a) -> m (Maybe a)
withDBusX f = withDBus $ \db -> do
forM (dbSesClient db) $ \ses -> do
bracket_ (requestXMonadName ses) (releaseXMonadName ses) $ f db
withDBus_ :: MonadUnliftIO m => (DBusState -> m a) -> m ()
withDBus_ = void . withDBus
withDBus :: MonadUnliftIO m => (DBusState -> m a) -> m a
withDBus = bracket connectDBus disconnectDBus
-- | Connect to the DBus
connectDBus :: MonadUnliftIO m => m DBusState
connectDBus = do
ses <- getDBusClient
sys <- getDBusClient
return DBusState {dbSesClient = ses, dbSysClient = sys}
-- | Disconnect from the DBus
disconnectDBus :: MonadUnliftIO m => DBusState -> m ()
disconnectDBus db = disc dbSesClient >> disc dbSysClient
where
disc f = maybe (return ()) disconnectDBusClient $ f db
-- | Connect to the DBus and request the XMonad name
connectDBusX :: MonadUnliftIO m => m DBusState
connectDBusX = do
db <- connectDBus
forM_ (dbSesClient db) requestXMonadName
return db
-- | Disconnect from DBus and release the XMonad name
disconnectDBusX :: MonadUnliftIO m => DBusState -> m ()
disconnectDBusX db = do
forM_ (dbSesClient db) releaseXMonadName
disconnectDBus db
-- | All exporter features to be assigned to the DBus
dbusExporters :: [Maybe SesClient -> SometimesIO]
dbusExporters = [exportScreensaver, exportIntelBacklight, exportClevoKeyboard]
releaseXMonadName :: MonadUnliftIO m => SesClient -> m ()
releaseXMonadName ses = liftIO $ void $ releaseName (toClient ses) xmonadBusName
requestXMonadName :: MonadUnliftIO m => SesClient -> m ()
requestXMonadName ses = do
res <- liftIO $ requestName (toClient ses) xmonadBusName []
-- TODO if the client is not released on shutdown the owner will be different
let msg
| res == NamePrimaryOwner = Nothing
| res == NameAlreadyOwner = Just $ "this process already owns " ++ xn
| res == NameInQueue
|| res == NameExists =
Just $ "another process owns " ++ xn
| otherwise = Just $ "unknown error when requesting " ++ xn
liftIO $ forM_ msg putStrLn
where
xn = "'" ++ formatBusName xmonadBusName ++ "'"