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

138 lines
4.0 KiB
Haskell
Raw Normal View History

--------------------------------------------------------------------------------
-- | DBus module for X11 screensave/DPMS control
2020-04-01 20:17:47 -04:00
module XMonad.Internal.DBus.Screensaver
( exportScreensaver
, callToggle
, callQuery
, matchSignal
, ssSignalDep
) where
2021-11-11 00:11:15 -05:00
import Control.Monad (void)
2020-03-25 18:35:04 -04:00
import DBus
import DBus.Client
import DBus.Internal
import qualified DBus.Introspection as I
2020-03-25 18:35:04 -04:00
import Graphics.X11.XScreenSaver
2021-06-19 00:54:01 -04:00
import Graphics.X11.Xlib.Display
2020-04-01 20:17:47 -04:00
import XMonad.Internal.DBus.Common
import XMonad.Internal.Dependency
import XMonad.Internal.Process
--------------------------------------------------------------------------------
-- | Low-level functions
type SSState = Bool -- true is enabled
ssExecutable :: String
ssExecutable = "xset"
toggle :: IO SSState
toggle = do
st <- query
-- TODO figure out how not to do this with shell commands
void $ createProcess' $ proc ssExecutable $ "s" : args st
-- TODO this assumes the command succeeds
return $ not st
where
args s = if s then ["off", "-dpms"] else ["on", "+dpms"]
query :: IO SSState
query = do
dpy <- openDisplay ""
xssi <- xScreenSaverQueryInfo dpy
closeDisplay dpy
return $ case xssi of
Just XScreenSaverInfo { xssi_state = ScreenSaverDisabled } -> False
Just XScreenSaverInfo { xssi_state = _ } -> True
-- TODO handle errors better (at least log them?)
Nothing -> False
--------------------------------------------------------------------------------
-- | DBus Interface
--
-- Define a methods to toggle the screensaver. This methods will emit signal
-- with the new state when called. Define another method to get the current
-- state.
ssPath :: ObjectPath
ssPath = objectPath_ "/screensaver"
interface :: InterfaceName
interface = interfaceName_ "org.xmonad.Screensaver"
memState :: MemberName
memState = memberName_ "State"
memToggle :: MemberName
memToggle = memberName_ "Toggle"
memQuery :: MemberName
memQuery = memberName_ "Query"
sigCurrentState :: Signal
sigCurrentState = signal ssPath interface memState
ruleCurrentState :: MatchRule
ruleCurrentState = matchAny
{ matchPath = Just ssPath
, matchInterface = Just interface
, matchMember = Just memState
}
emitState :: Client -> SSState -> IO ()
emitState client sss = emit client $ sigCurrentState { signalBody = [toVariant sss] }
bodyGetCurrentState :: [Variant] -> Maybe SSState
bodyGetCurrentState [b] = fromVariant b :: Maybe SSState
bodyGetCurrentState _ = Nothing
2020-04-01 20:17:47 -04:00
--------------------------------------------------------------------------------
-- | Exported haskell API
exportScreensaver :: Maybe Client -> FeatureIO
exportScreensaver client = Feature
2021-11-22 23:28:54 -05:00
{ ftrDepTree = DBusTree (Single cmd) client [Bus xmonadBusName] [Executable ssExecutable]
, ftrName = "screensaver interface"
, ftrWarning = Default
2021-11-11 00:11:15 -05:00
}
where
cmd cl = export cl ssPath defaultInterface
2021-11-11 00:11:15 -05:00
{ interfaceName = interface
, interfaceMethods =
[ autoMethod memToggle $ emitState cl =<< toggle
2021-11-11 00:11:15 -05:00
, autoMethod memQuery query
]
, interfaceSignals = [sig]
}
sig = I.Signal
{ I.signalName = memState
, I.signalArgs =
[
I.SignalArg
{ I.signalArgName = "enabled"
, I.signalArgType = TypeBoolean
}
]
2021-11-11 00:11:15 -05:00
}
callToggle :: Maybe Client -> FeatureIO
2021-11-27 01:06:49 -05:00
callToggle =
featureEndpoint "screensaver toggle" xmonadBusName ssPath interface memToggle
2021-11-21 17:54:00 -05:00
callQuery :: Client -> IO (Maybe SSState)
callQuery client = do
reply <- callMethod client xmonadBusName ssPath interface memQuery
2021-11-21 16:58:01 -05:00
return $ either (const Nothing) bodyGetCurrentState reply
2021-11-23 18:28:38 -05:00
matchSignal :: (Maybe SSState -> IO ()) -> Client -> IO ()
matchSignal cb =
fmap void . addMatchCallback ruleCurrentState $ cb . bodyGetCurrentState
2021-11-21 00:53:45 -05:00
2021-11-22 23:02:23 -05:00
ssSignalDep :: DBusDep
2021-11-21 23:55:19 -05:00
ssSignalDep = Endpoint xmonadBusName ssPath interface $ Signal_ memState