{-# LANGUAGE RecordWildCards #-}
import Control.Monad
import qualified Data.Map as M
import Control.Exception as E
import Control.Concurrent
import Foreign
import Foreign.Ptr
import Data.Bits ((.|.))
import Text.Printf
import Graphics.X11
import Graphics.X11.Xlib.Extras
import Graphics.X11.Xlib.Atom
import System.FilePath
import System.Environment
import System.Wacom.Daemon
import System.Wacom.Profiles
import System.Wacom.X11
import System.Wacom.Matching
import System.Wacom.Notify
onCurrentWindowChange :: WacomHandle -> Config -> WindowInfo -> IO ()
onCurrentWindowChange wh cfg wi = do
print wi
rOld <- getProfileName wh
let newProfile = selectProfile (mcMatching cfg) wi
case rOld of
Left err -> putStrLn $ "Cant get old profile: " ++ err
Right old -> do
putStrLn $ "Old profile: " ++ old
when (newProfile /= old) $ do
r <- setProfile wh newProfile
case r of
Right p -> do
putStrLn $ "Selecting profile: " ++ p
when (mcNotify cfg) $
notify "Tablet profile" $ "New tablet profile selected: " ++ p
Left err -> putStrLn $ "Error: " ++ err
return ()
runModeAction :: WacomHandle -> Config -> ModeAction -> IO ()
runModeAction wh cfg ToggleRingMode = do
r <- toggleRingMode wh
case r of
Left err -> putStrLn $ "Error: " ++ err
Right res -> do
putStrLn $ "Ring mode: " ++ res
when (mcNotify cfg) $ do
rm <- getRingModeName wh
case rm of
Left err -> putStrLn $ "Error: " ++ err
Right name -> notify "Ring Mode" $ "New ring mode selected: " ++ name
runModeAction wh _ (SetMappingArea idx) = do
setMapArea wh idx
return ()
getConfigFile :: IO FilePath
getConfigFile = do
home <- getEnv "HOME"
return $ home </> ".config" </> "hswcmd.yaml"
main :: IO ()
main = do
ecfg <- readConfig =<< getConfigFile
cfg <- case ecfg of
Left err -> fail $ show err
Right cfg -> return cfg
wh <- newWacomHandle (mcProfilesConfig cfg)
forkIO $ udevMonitor wh
setProfile wh "Default"
setRingMode wh 0
setMapArea wh 0
withDisplay "" $ \dpy -> do
let rootw = defaultRootWindow dpy
numlock <- getNumlockMask dpy
grabHotkeys dpy rootw numlock $ getHotkeys (mcKeyMap cfg)
keymap <- compileKeyMap dpy $ mcKeyMap cfg
-- We need only PropertyEvent (toggled when active window is changed)
-- and KeyEvent (when keyboard key is pressed)
selectInput dpy rootw (propertyChangeMask .|. keyPressMask)
forever $ do
allocaXEvent $ \xptr -> do
nextEvent dpy xptr
ev <- getEvent xptr
case ev of
PropertyEvent {..} -> do
mbName <- getAtomName dpy ev_atom
case mbName of
-- We are interested only in such events - active window changed
Just "_NET_ACTIVE_WINDOW" -> do
mbWindow <- getWindowInfo dpy ev_atom ev_window
case mbWindow of
Just wi -> onCurrentWindowChange wh cfg wi
Nothing -> return ()
_ -> return ()
KeyEvent {..} -> do
-- Key pressed
when (ev_event_type == keyPress) $ do
keysym <- keycodeToKeysym dpy ev_keycode 0
let mask = cleanMask numlock ev_state
case M.lookup (mask,keysym) keymap of
Nothing -> putStrLn $ "Unknown key " ++ show (mask,keysym)
Just action -> runModeAction wh cfg action
return ()
_ -> putStrLn $ "Unexpected event: " ++ show ev