wild-bind-x11 0.2.0.14 → 0.2.0.15
raw patch · 16 files changed
+751/−769 lines, 16 filesdep ~basedep ~timesetup-changedPVP ok
version bump matches the API change (PVP)
Dependency ranges changed: base, time
API changes (from Hackage documentation)
Files
- ChangeLog.md +4/−0
- Setup.hs +1/−1
- src/WildBind/X11.hs +39/−50
- src/WildBind/X11/Emulate.hs +16/−22
- src/WildBind/X11/Emulate/Example.hs +6/−13
- src/WildBind/X11/Internal/FrontEnd.hs +51/−52
- src/WildBind/X11/Internal/GrabMan.hs +27/−30
- src/WildBind/X11/Internal/Key.hs +106/−109
- src/WildBind/X11/Internal/NotificationDebouncer.hs +17/−16
- src/WildBind/X11/Internal/Window.hs +40/−36
- src/WildBind/X11/KeySym.hs +361/−361
- test/WildBind/X11/EmulateSpec.hs +22/−23
- test/WildBind/X11/Internal/NotificationDebouncerSpec.hs +8/−6
- test/WildBind/X11/TestUtil.hs +12/−12
- test/WildBind/X11Spec.hs +38/−35
- wild-bind-x11.cabal +3/−3
ChangeLog.md view
@@ -1,5 +1,9 @@ # Revision history for wild-bind-x11 +## 0.2.0.15 -- 2022-11-28++* Confirm test with ghc-9.2.5.+ ## 0.2.0.14 -- 2021-11-23 * Confirm test with `semigroups-0.20`.
Setup.hs view
@@ -1,2 +1,2 @@-import Distribution.Simple+import Distribution.Simple main = defaultMain
src/WildBind/X11.hs view
@@ -2,58 +2,47 @@ -- Module: WildBind.X11 -- Description: X11-specific implementation for WildBind -- Maintainer: Toshio Ito <debug.ito@gmail.com>--- +-- -- This module exports a 'FrontEnd' for X11 environments. module WildBind.X11- ( -- * X11 front-end- withFrontEnd,- XKeyInput(..),- -- * Windows in X11- Window,- ActiveWindow,- -- ** Getters- winInstance,- winClass,- winName,- -- * Keys in X11- XKeyEvent(..),- XMod(..),- KeyEventType(..),- ToXKeyEvent(..),- -- ** Setters- press,- release,- shift,- ctrl,- alt,- super,- addXMod,- -- * X11Front- X11Front,- withX11Front,- makeFrontEnd,- defaultRootWindow- ) where+ ( -- * X11 front-end+ withFrontEnd+ , XKeyInput (..)+ -- * Windows in X11+ , Window+ , ActiveWindow+ -- ** Getters+ , winInstance+ , winClass+ , winName+ -- * Keys in X11+ , XKeyEvent (..)+ , XMod (..)+ , KeyEventType (..)+ , ToXKeyEvent (..)+ -- ** Setters+ , press+ , release+ , shift+ , ctrl+ , alt+ , super+ , addXMod+ -- * X11Front+ , X11Front+ , withX11Front+ , makeFrontEnd+ , defaultRootWindow+ ) where -import WildBind (FrontEnd)-import qualified WildBind.Description as WBD+import WildBind (FrontEnd)+import qualified WildBind.Description as WBD -import WildBind.X11.Internal.FrontEnd- ( X11Front,- withFrontEnd,- withX11Front,- makeFrontEnd,- defaultRootWindow- )-import WildBind.X11.Internal.Key- ( XKeyInput(..),- XKeyEvent(..),- XMod(..),- ToXKeyEvent(..),- KeyEventType(..),- press, release,- addXMod,- shift, ctrl, alt, super- )-import WildBind.X11.Internal.Window (ActiveWindow, Window, winInstance, winClass, winName)+import WildBind.X11.Internal.FrontEnd (X11Front, defaultRootWindow, makeFrontEnd,+ withFrontEnd, withX11Front)+import WildBind.X11.Internal.Key (KeyEventType (..), ToXKeyEvent (..),+ XKeyEvent (..), XKeyInput (..), XMod (..), addXMod,+ alt, ctrl, press, release, shift, super)+import WildBind.X11.Internal.Window (ActiveWindow, Window, winClass, winInstance,+ winName)
src/WildBind/X11/Emulate.hs view
@@ -10,30 +10,24 @@ -- -- @since 0.2.0.0 module WildBind.X11.Emulate- ( -- * Create key inputs- sendKeyTo,- sendKey,- pushTo,- push,- -- * Key remap binding- remap,- remapR- ) where+ ( -- * Create key inputs+ sendKeyTo+ , sendKey+ , pushTo+ , push+ -- * Key remap binding+ , remap+ , remapR+ ) where -import Control.Monad.IO.Class (MonadIO(liftIO))-import Control.Monad.Reader.Class (MonadReader(ask))-import WildBind.Binding (Binding', bindsF, on, run)+import Control.Monad.IO.Class (MonadIO (liftIO))+import Control.Monad.Reader.Class (MonadReader (ask))+import WildBind.Binding (Binding', bindsF, on, run) -import WildBind.X11.Internal.FrontEnd- ( X11Front(..)- )-import WildBind.X11.Internal.Key- ( ToXKeyEvent(..), KeyEventType(..), XKeyEvent,- xSendKeyEvent, press, release- )-import WildBind.X11.Internal.Window- ( Window, ActiveWindow, winID- )+import WildBind.X11.Internal.FrontEnd (X11Front (..))+import WildBind.X11.Internal.Key (KeyEventType (..), ToXKeyEvent (..), XKeyEvent,+ press, release, xSendKeyEvent)+import WildBind.X11.Internal.Window (ActiveWindow, Window, winID) -- | Send a X11 key event to a 'Window'. sendKeyTo :: (ToXKeyEvent k, MonadIO m)
src/WildBind/X11/Emulate/Example.hs view
@@ -7,20 +7,13 @@ -- This is an example of using "WildBind.X11.Emulate". See the source. -- -- @since 0.2.0.0-module WildBind.X11.Emulate.Example- where+module WildBind.X11.Emulate.Example where -import WildBind- ( Binding,- wildBind, bindsF, on, as, run- )-import WildBind.X11- ( X11Front, XKeyEvent, ActiveWindow,- withX11Front, makeFrontEnd,- alt, ctrl, press, release- )-import WildBind.X11.KeySym (xK_c, xK_w)-import WildBind.X11.Emulate (sendKey)+import WildBind (Binding, as, bindsF, on, run, wildBind)+import WildBind.X11 (ActiveWindow, X11Front, XKeyEvent, alt, ctrl, makeFrontEnd,+ press, release, withX11Front)+import WildBind.X11.Emulate (sendKey)+import WildBind.X11.KeySym (xK_c, xK_w) main :: IO () main = withX11Front $ \x11 -> wildBind (myBinding x11) (makeFrontEnd x11)
src/WildBind/X11/Internal/FrontEnd.hs view
@@ -5,47 +5,44 @@ -- -- __This is an internal module. Package users should not rely on this.__ module WildBind.X11.Internal.FrontEnd- ( -- * X11Front- X11Front(..),- withFrontEnd,- withX11Front,- makeFrontEnd,- defaultRootWindow- ) where+ ( -- * X11Front+ X11Front (..)+ , withFrontEnd+ , withX11Front+ , makeFrontEnd+ , defaultRootWindow+ ) where -import Control.Applicative ((<$>), empty)-import Control.Concurrent (rtsSupportsBoundThreads)-import Control.Concurrent.STM (atomically, TChan, newTChanIO, tryReadTChan, writeTChan)-import Control.Exception (bracket, throwIO)-import Control.Monad (when, filterM, mapM_)-import Control.Monad.IO.Class (liftIO)-import Control.Monad.Trans.Cont (ContT(ContT), runContT)-import Control.Monad.Trans.Maybe (MaybeT, runMaybeT)-import Control.Monad.Trans.Writer (WriterT, execWriterT, tell)-import Data.Bits ((.|.))-import Data.IORef (IORef, newIORef, readIORef, writeIORef)-import qualified Graphics.X11.Xlib as Xlib+import Control.Applicative (empty, (<$>))+import Control.Concurrent (rtsSupportsBoundThreads)+import Control.Concurrent.STM (TChan, atomically, newTChanIO,+ tryReadTChan, writeTChan)+import Control.Exception (bracket, throwIO)+import Control.Monad (filterM, mapM_, when)+import Control.Monad.IO.Class (liftIO)+import Control.Monad.Trans.Cont (ContT (ContT), runContT)+import Control.Monad.Trans.Maybe (MaybeT, runMaybeT)+import Control.Monad.Trans.Writer (WriterT, execWriterT, tell)+import Data.Bits ((.|.))+import Data.IORef (IORef, newIORef, readIORef,+ writeIORef)+import qualified Graphics.X11.Xlib as Xlib -import WildBind- ( FrontEnd(FrontEnd, frontDefaultDescription, frontSetGrab, frontUnsetGrab, frontNextEvent),- FrontEvent(FEInput,FEChange)- )-import qualified WildBind.Description as WBD+import WildBind (FrontEnd (FrontEnd, frontDefaultDescription, frontNextEvent, frontSetGrab, frontUnsetGrab),+ FrontEvent (FEChange, FEInput))+import qualified WildBind.Description as WBD -import WildBind.X11.Internal.Key- ( xKeyEventToXKeyInput,- xGrabKey, xUngrabKey,- XKeyInput(..), KeyMaskMap, getKeyMaskMap,- KeyEventType(..)- )-import WildBind.X11.Internal.Window- ( ActiveWindow,getActiveWindow, Window,- winInstance, winClass, winName, emptyWindow,- defaultRootWindowForDisplay- )+import qualified WildBind.X11.Internal.GrabMan as GM+import WildBind.X11.Internal.Key (KeyEventType (..), KeyMaskMap,+ XKeyInput (..), getKeyMaskMap,+ xGrabKey, xKeyEventToXKeyInput,+ xUngrabKey) import qualified WildBind.X11.Internal.NotificationDebouncer as Ndeb-import qualified WildBind.X11.Internal.GrabMan as GM+import WildBind.X11.Internal.Window (ActiveWindow, Window,+ defaultRootWindowForDisplay,+ emptyWindow, getActiveWindow,+ winClass, winInstance, winName) -- | The X11 front-end. @k@ is the input key type. --@@ -57,14 +54,15 @@ -- for this API to change in the future than 'FrontEnd'. -- -- @since 0.2.0.0-data X11Front k =- X11Front { x11Display :: Xlib.Display,- x11Debouncer :: Ndeb.Debouncer,- x11PrevActiveWindow :: IORef (Maybe ActiveWindow),- x11PendingEvents :: TChan (FrontEvent ActiveWindow k),- x11KeyMaskMap :: KeyMaskMap,- x11GrabMan :: IORef (GM.GrabMan k)- }+data X11Front k+ = X11Front+ { x11Display :: Xlib.Display+ , x11Debouncer :: Ndeb.Debouncer+ , x11PrevActiveWindow :: IORef (Maybe ActiveWindow)+ , x11PendingEvents :: TChan (FrontEvent ActiveWindow k)+ , x11KeyMaskMap :: KeyMaskMap+ , x11GrabMan :: IORef (GM.GrabMan k)+ } x11PopPendingEvent :: X11Front k -> IO (Maybe (FrontEvent ActiveWindow k)) x11PopPendingEvent f = atomically $ tryReadTChan $ x11PendingEvents f@@ -82,7 +80,7 @@ -- front-end state. 'ActiveWindow' keeps information about the window -- currently active. As for the input type @i@, this 'FrontEnd' gets -- keyboard events from the X server.--- +-- -- CAVEATS -- -- Code using this function must be compiled@@ -141,10 +139,11 @@ tellElem :: Monad m => a -> WriterT [a] m () tellElem a = tell [a] -data InternalEvent = IEKey KeyEventType- | IEDebounced- | IEActiveWindow- | IEUnknown+data InternalEvent+ = IEKey KeyEventType+ | IEDebounced+ | IEActiveWindow+ | IEUnknown identifyEvent :: Ndeb.Debouncer -> Xlib.XEventPtr -> IO InternalEvent identifyEvent deb xev = do@@ -179,13 +178,13 @@ isSignificantEvent front (FEChange new_state) = do m_old_state <- liftIO $ readIORef $ x11PrevActiveWindow front case m_old_state of- Nothing -> return True+ Nothing -> return True Just old_state -> return (not $ new_state == old_state) isSignificantEvent _ _ = return True updateState :: X11Front k -> FrontEvent ActiveWindow k -> IO () updateState front fev = case fev of- (FEInput _) -> return ()+ (FEInput _) -> return () (FEChange s) -> writeIORef (x11PrevActiveWindow front) (Just s) nextEvent :: (XKeyInput k) => X11Front k -> IO (FrontEvent ActiveWindow k)@@ -194,7 +193,7 @@ mpending <- x11PopPendingEvent handle case mpending of Just eve -> return eve- Nothing -> nextEventFromX11+ Nothing -> nextEventFromX11 nextEventFromX11 = Xlib.allocaXEvent $ \xev -> do Xlib.nextEvent (x11Display handle) xev got_events <- processEvents xev
src/WildBind/X11/Internal/GrabMan.hs view
@@ -17,26 +17,23 @@ -- 'GrabField', we need to grab it if and only if there is at least -- one grabbed input symbol for the 'GrabField'. module WildBind.X11.Internal.GrabMan- ( GrabMan,- GrabOp(..),- new,- modify- ) where+ ( GrabMan+ , GrabOp (..)+ , new+ , modify+ ) where -import Control.Monad (forM_)-import Data.IORef (IORef, newIORef, readIORef, writeIORef)-import Data.Foldable (foldr)-import Data.List.NonEmpty (NonEmpty)-import qualified Data.Map.Strict as M-import Data.Monoid (Monoid(..), (<>))-import qualified Data.Set as S-import qualified Graphics.X11.Xlib as Xlib+import Control.Monad (forM_)+import Data.Foldable (foldr)+import Data.IORef (IORef, newIORef, readIORef, writeIORef)+import Data.List.NonEmpty (NonEmpty)+import qualified Data.Map.Strict as M+import Data.Monoid (Monoid (..), (<>))+import qualified Data.Set as S+import qualified Graphics.X11.Xlib as Xlib -import WildBind.X11.Internal.Key- ( XKeyEvent(..), press, KeyEventType(..),- KeyMaskMap, XKeyInput(..),- xGrabKey, xUngrabKey- )+import WildBind.X11.Internal.Key (KeyEventType (..), KeyMaskMap, XKeyEvent (..),+ XKeyInput (..), press, xGrabKey, xUngrabKey) -- | Unit of key grabs in X11. X server manages state of key grabs -- independently for each 'GrabField'.@@ -62,27 +59,27 @@ in ( if removed then M.delete field inputs else M.insert field new_grabbed inputs,- + removed ) -- | Grab operation. Either \"set grab\" or \"unset grab\".-data GrabOp = DoSetGrab | DoUnsetGrab deriving (Show,Eq,Ord)+data GrabOp = DoSetGrab | DoUnsetGrab deriving (Eq, Ord, Show) modifyG :: Ord k => GrabOp -> GrabField -> k -> GrabbedInputs k -> (GrabbedInputs k, Bool) modifyG op = case op of- DoSetGrab -> insertG+ DoSetGrab -> insertG DoUnsetGrab -> deleteG -- | The key grab manager.-data GrabMan k =- GrabMan- { gmKeyMaskMap :: KeyMaskMap,- gmDisplay :: Xlib.Display,- gmRootWindow :: Xlib.Window,- gmGrabbedInputs :: GrabbedInputs k- }- deriving (Show,Eq,Ord)+data GrabMan k+ = GrabMan+ { gmKeyMaskMap :: KeyMaskMap+ , gmDisplay :: Xlib.Display+ , gmRootWindow :: Xlib.Window+ , gmGrabbedInputs :: GrabbedInputs k+ }+ deriving (Eq, Ord, Show) -- | Create a new 'GrabMan'. new :: KeyMaskMap -> Xlib.Display -> Xlib.Window -> IO (IORef (GrabMan k))@@ -123,6 +120,6 @@ writeIORef gm_ref new_gm forM_ changed_fields $ \(keysym, mask) -> do case op of- DoSetGrab -> xGrabKey disp rwin keysym mask+ DoSetGrab -> xGrabKey disp rwin keysym mask DoUnsetGrab -> xUngrabKey disp rwin keysym mask
src/WildBind/X11/Internal/Key.hs view
@@ -1,4 +1,6 @@-{-# LANGUAGE GeneralizedNewtypeDeriving, TypeSynonymInstances, OverloadedStrings #-}+{-# LANGUAGE GeneralizedNewtypeDeriving #-}+{-# LANGUAGE OverloadedStrings #-}+{-# LANGUAGE TypeSynonymInstances #-} -- | -- Module: WildBind.X11.Internal.Key -- Description: types and functions related to key symbols and their conversion@@ -6,75 +8,73 @@ -- -- __This is an internal module. Package users should not rely on this.__ module WildBind.X11.Internal.Key- ( -- * Key- XKeyInput(..),- xKeyEventToXKeyInput,- KeyEventType(..),- -- * Modifiers- KeyMaskMap(..),- getKeyMaskMap,- -- * XKeyEvent- XKeyEvent(..),- XMod(..),- ToXKeyEvent(..),- addXMod,- press,- release,- shift,- ctrl,- alt,- super,- -- * Grabs- xGrabKey,- xUngrabKey,- -- * Event generation- xSendKeyEvent- ) where+ ( -- * Key+ XKeyInput (..)+ , xKeyEventToXKeyInput+ , KeyEventType (..)+ -- * Modifiers+ , KeyMaskMap (..)+ , getKeyMaskMap+ -- * XKeyEvent+ , XKeyEvent (..)+ , XMod (..)+ , ToXKeyEvent (..)+ , addXMod+ , press+ , release+ , shift+ , ctrl+ , alt+ , super+ -- * Grabs+ , xGrabKey+ , xUngrabKey+ -- * Event generation+ , xSendKeyEvent+ ) where -import Control.Applicative ((<$>), (<*>), (<|>))-import Control.Monad (forM_)-import Control.Monad.IO.Class (liftIO)-import Control.Monad.Trans.Maybe (MaybeT(MaybeT))-import Data.Bits ((.|.), (.&.))-import qualified Data.Bits as Bits-import Data.Foldable (foldr, fold)-import Data.List (nub)-import Data.List.NonEmpty (NonEmpty(..))-import qualified Data.Map as M-import Data.Maybe (mapMaybe, listToMaybe)-import Data.Monoid ((<>))-import qualified Data.Set as S-import qualified Data.Text as T+import Control.Applicative ((<$>), (<*>), (<|>))+import Control.Monad (forM_)+import Control.Monad.IO.Class (liftIO)+import Control.Monad.Trans.Maybe (MaybeT (MaybeT))+import Data.Bits ((.&.), (.|.))+import qualified Data.Bits as Bits+import Data.Foldable (fold, foldr)+import Data.List (nub)+import Data.List.NonEmpty (NonEmpty (..))+import qualified Data.Map as M+import Data.Maybe (listToMaybe, mapMaybe)+import Data.Monoid ((<>))+import qualified Data.Set as S+import qualified Data.Text as T import qualified Foreign-import qualified Graphics.X11.Xlib as Xlib-import qualified Graphics.X11.Xlib.Extras as XlibE+import qualified Graphics.X11.Xlib as Xlib+import qualified Graphics.X11.Xlib.Extras as XlibE -import WildBind.Description (Describable(..))-import qualified WildBind.Input.NumPad as NumPad+import WildBind.Description (Describable (..))+import qualified WildBind.Input.NumPad as NumPad -- | Whether the key is pressed or released. -- -- @since 0.2.0.0-data KeyEventType = KeyPress- | KeyRelease- deriving (Show,Eq,Ord,Bounded,Enum)+data KeyEventType = KeyPress | KeyRelease deriving (Bounded, Enum, Eq, Ord, Show) -- | 'Xlib.KeyMask' values assigned to each modifier keys/states. If -- the modifier doesn't exist, the mask is 0. -- -- @since 0.2.0.0-data KeyMaskMap =- KeyMaskMap- { maskShift :: Xlib.KeyMask,- maskControl :: Xlib.KeyMask,- maskAlt :: Xlib.KeyMask,- maskSuper :: Xlib.KeyMask,- maskNumLock :: Xlib.KeyMask,- maskCapsLock :: Xlib.KeyMask,- maskShiftLock :: Xlib.KeyMask,- maskScrollLock :: Xlib.KeyMask- }- deriving (Show,Eq,Ord)+data KeyMaskMap+ = KeyMaskMap+ { maskShift :: Xlib.KeyMask+ , maskControl :: Xlib.KeyMask+ , maskAlt :: Xlib.KeyMask+ , maskSuper :: Xlib.KeyMask+ , maskNumLock :: Xlib.KeyMask+ , maskCapsLock :: Xlib.KeyMask+ , maskShiftLock :: Xlib.KeyMask+ , maskScrollLock :: Xlib.KeyMask+ }+ deriving (Eq, Ord, Show) isMasked :: KeyMaskMap -> (KeyMaskMap -> Xlib.KeyMask) -> Xlib.KeyMask -> Bool isMasked kmmap accessor target = if (target .&. accessor kmmap) == 0@@ -99,29 +99,29 @@ -- | Partial inverse of 'toKeySym'. fromKeySymDef :: (Bounded k, Enum k) => (k -> Xlib.KeySym) -> Xlib.KeySym -> Maybe k-fromKeySymDef to_conv ks = M.lookup ks $ M.fromList $ map (\n -> (to_conv n, n)) $ enumFromTo minBound maxBound +fromKeySymDef to_conv ks = M.lookup ks $ M.fromList $ map (\n -> (to_conv n, n)) $ enumFromTo minBound maxBound -- | This input event captures the 'KeyRelease' event only. That way, -- you can deliver events to the window that originally has the -- keyboard focus. instance XKeyInput NumPad.NumPadUnlocked where toKeySym n = case n of- NumPad.NumUp -> Xlib.xK_KP_Up- NumPad.NumDown -> Xlib.xK_KP_Down- NumPad.NumLeft -> Xlib.xK_KP_Left- NumPad.NumRight -> Xlib.xK_KP_Right- NumPad.NumHome -> Xlib.xK_KP_Home- NumPad.NumPageUp -> Xlib.xK_KP_Page_Up+ NumPad.NumUp -> Xlib.xK_KP_Up+ NumPad.NumDown -> Xlib.xK_KP_Down+ NumPad.NumLeft -> Xlib.xK_KP_Left+ NumPad.NumRight -> Xlib.xK_KP_Right+ NumPad.NumHome -> Xlib.xK_KP_Home+ NumPad.NumPageUp -> Xlib.xK_KP_Page_Up NumPad.NumPageDown -> Xlib.xK_KP_Page_Down- NumPad.NumEnd -> Xlib.xK_KP_End- NumPad.NumCenter -> Xlib.xK_KP_Begin- NumPad.NumInsert -> Xlib.xK_KP_Insert- NumPad.NumDelete -> Xlib.xK_KP_Delete- NumPad.NumEnter -> Xlib.xK_KP_Enter- NumPad.NumDivide -> Xlib.xK_KP_Divide- NumPad.NumMulti -> Xlib.xK_KP_Multiply- NumPad.NumMinus -> Xlib.xK_KP_Subtract- NumPad.NumPlus -> Xlib.xK_KP_Add+ NumPad.NumEnd -> Xlib.xK_KP_End+ NumPad.NumCenter -> Xlib.xK_KP_Begin+ NumPad.NumInsert -> Xlib.xK_KP_Insert+ NumPad.NumDelete -> Xlib.xK_KP_Delete+ NumPad.NumEnter -> Xlib.xK_KP_Enter+ NumPad.NumDivide -> Xlib.xK_KP_Divide+ NumPad.NumMulti -> Xlib.xK_KP_Multiply+ NumPad.NumMinus -> Xlib.xK_KP_Subtract+ NumPad.NumPlus -> Xlib.xK_KP_Add fromKeyEvent _ KeyPress _ _ = Nothing fromKeyEvent kmmask KeyRelease keysym mask = if is_numlocked then Nothing@@ -134,24 +134,24 @@ -- keyboard focus. instance XKeyInput NumPad.NumPadLocked where toKeySym n = case n of- NumPad.NumL0 -> Xlib.xK_KP_0- NumPad.NumL1 -> Xlib.xK_KP_1- NumPad.NumL2 -> Xlib.xK_KP_2- NumPad.NumL3 -> Xlib.xK_KP_3- NumPad.NumL4 -> Xlib.xK_KP_4- NumPad.NumL5 -> Xlib.xK_KP_5- NumPad.NumL6 -> Xlib.xK_KP_6- NumPad.NumL7 -> Xlib.xK_KP_7- NumPad.NumL8 -> Xlib.xK_KP_8- NumPad.NumL9 -> Xlib.xK_KP_9+ NumPad.NumL0 -> Xlib.xK_KP_0+ NumPad.NumL1 -> Xlib.xK_KP_1+ NumPad.NumL2 -> Xlib.xK_KP_2+ NumPad.NumL3 -> Xlib.xK_KP_3+ NumPad.NumL4 -> Xlib.xK_KP_4+ NumPad.NumL5 -> Xlib.xK_KP_5+ NumPad.NumL6 -> Xlib.xK_KP_6+ NumPad.NumL7 -> Xlib.xK_KP_7+ NumPad.NumL8 -> Xlib.xK_KP_8+ NumPad.NumL9 -> Xlib.xK_KP_9 NumPad.NumLDivide -> Xlib.xK_KP_Divide- NumPad.NumLMulti -> Xlib.xK_KP_Multiply- NumPad.NumLMinus -> Xlib.xK_KP_Subtract- NumPad.NumLPlus -> Xlib.xK_KP_Add- NumPad.NumLEnter -> Xlib.xK_KP_Enter+ NumPad.NumLMulti -> Xlib.xK_KP_Multiply+ NumPad.NumLMinus -> Xlib.xK_KP_Subtract+ NumPad.NumLPlus -> Xlib.xK_KP_Add+ NumPad.NumLEnter -> Xlib.xK_KP_Enter NumPad.NumLPeriod -> Xlib.xK_KP_Delete -- XKeysymToKeycode() didn't return the correct keycode for XK_KP_Decimal in numpaar code...- + toModifierMasks kmmap _ = return $ maskNumLock kmmap -- Xlib handles the [(.) (Delete)] key in a weird way. In the input@@ -262,24 +262,21 @@ -- | X11 key modifiers. -- -- @since 0.2.0.0-data XMod = Shift- | Ctrl- | Alt- | Super- deriving (Show,Eq,Ord,Enum,Bounded)+data XMod = Shift | Ctrl | Alt | Super deriving (Bounded, Enum, Eq, Ord, Show) -- | High-level X11 key event. -- -- @since 0.2.0.0-data XKeyEvent =- XKeyEvent- { xKeyEventType :: KeyEventType, - xKeyEventMods :: S.Set XMod, -- ^ set of key modifiers enabled.- xKeyEventKeySym :: Xlib.KeySym- -- ^ X11 KeySym for the key. "WildBind.X11.KeySym" re-exports- -- 'KeySym' values.- }- deriving (Show,Eq,Ord)+data XKeyEvent+ = XKeyEvent+ { xKeyEventType :: KeyEventType+ , xKeyEventMods :: S.Set XMod+ -- ^ set of key modifiers enabled.+ , xKeyEventKeySym :: Xlib.KeySym+ -- ^ X11 KeySym for the key. "WildBind.X11.KeySym" re-exports+ -- 'KeySym' values.+ }+ deriving (Eq, Ord, Show) -- | 'fromKeyEvent' always returns 'Just'. instance XKeyInput XKeyEvent where@@ -309,14 +306,14 @@ where mods_str = fold $ S.map (\m -> show m ++ "+") mods ev_txt = case ev of- KeyPress -> "press "+ KeyPress -> "press " KeyRelease -> "release " xModToKeyMask :: KeyMaskMap -> XMod -> Xlib.KeyMask xModToKeyMask kmmap modi = case modi of Shift -> maskShift kmmap- Ctrl -> maskControl kmmap- Alt -> maskAlt kmmap+ Ctrl -> maskControl kmmap+ Alt -> maskAlt kmmap Super -> maskSuper kmmap xModsToKeyMask :: KeyMaskMap -> S.Set XMod -> Xlib.KeyMask@@ -332,7 +329,7 @@ scl <- [0, maskScrollLock kmmap] return (numl .|. capsl .|. shiftl .|. scl) where- toNonEmpty [] = return 0+ toNonEmpty [] = return 0 -- the result should always include 0, so the above case is not really necessary. toNonEmpty (x:rest) = x :| rest @@ -402,10 +399,10 @@ propagate = True event_type = xKeyEventType key_event event_mask = case event_type of- KeyPress -> Xlib.keyPressMask+ KeyPress -> Xlib.keyPressMask KeyRelease -> Xlib.keyReleaseMask xevent_type = case event_type of- KeyPress -> Xlib.keyPress+ KeyPress -> Xlib.keyPress KeyRelease -> Xlib.keyRelease setupXEvent xev = do key_code <- Xlib.keysymToKeycode disp $ xKeyEventKeySym key_event
src/WildBind/X11/Internal/NotificationDebouncer.hs view
@@ -24,9 +24,9 @@ -- -- * Sometimes I could not obtain the current active window. Instead, -- I ended up with getting the previous active window.--- +-- -- * Sometimes GetWindowProperty blocked forever.--- +-- -- So, as a workaround, we debounce the raw notification events and -- generate a ClientMessage X11 event. When we get the ClientMessage, -- we update the state.@@ -34,22 +34,23 @@ -- Toshio's personal note: 2015/05/06, 2010/12/05 - 19 module WildBind.X11.Internal.NotificationDebouncer- ( Debouncer,- withDebouncer,- notify,- xEventMask,- isDebouncedEvent- ) where+ ( Debouncer+ , withDebouncer+ , notify+ , xEventMask+ , isDebouncedEvent+ ) where -import Control.Exception (bracket)-import qualified Control.FoldDebounce as Fdeb-import qualified Graphics.X11.Xlib as Xlib+import Control.Exception (bracket)+import qualified Control.FoldDebounce as Fdeb+import qualified Graphics.X11.Xlib as Xlib import qualified Graphics.X11.Xlib.Extras as XlibE -data Debouncer = Debouncer- { ndTrigger :: Fdeb.Trigger () (),- ndMessageType :: Xlib.Atom- }+data Debouncer+ = Debouncer+ { ndTrigger :: Fdeb.Trigger () ()+ , ndMessageType :: Xlib.Atom+ } -- | Create a Debouncer and run the specified action. withDebouncer :: Xlib.Display -> (Debouncer -> IO a) -> IO a@@ -91,4 +92,4 @@ let exp_type = ndMessageType deb case ev of XlibE.ClientMessageEvent _ _ _ _ _ got_type _ -> return (got_type == exp_type)- _ -> return False+ _ -> return False
src/WildBind/X11/Internal/Window.hs view
@@ -6,32 +6,32 @@ -- -- __This is an internal module. Package users should not rely on this.__ module WildBind.X11.Internal.Window- ( -- * The 'Window' data type- Window,- ActiveWindow,- emptyWindow,- fromWinID,- -- * Accessor functions for 'Window'- winInstance,- winClass,- winName,- -- ** project-internal accessor- winID,- -- * Functions- getActiveWindow,- defaultRootWindowForDisplay- ) where+ ( -- * The 'Window' data type+ Window+ , ActiveWindow+ , emptyWindow+ , fromWinID+ -- * Accessor functions for 'Window'+ , winInstance+ , winClass+ , winName+ -- ** project-internal accessor+ , winID+ -- * Functions+ , getActiveWindow+ , defaultRootWindowForDisplay+ ) where -import Control.Applicative ((<$>),(<|>),empty)-import Control.Monad (guard)-import Control.Monad.IO.Class (liftIO)-import Control.Monad.Trans.Maybe (MaybeT(MaybeT),runMaybeT)-import Data.Maybe (listToMaybe)-import Data.Text (Text)-import qualified Data.Text as Text+import Control.Applicative (empty, (<$>), (<|>))+import Control.Monad (guard)+import Control.Monad.IO.Class (liftIO)+import Control.Monad.Trans.Maybe (MaybeT (MaybeT), runMaybeT)+import Data.Maybe (listToMaybe)+import Data.Text (Text)+import qualified Data.Text as Text import qualified Foreign-import qualified Graphics.X11.Xlib as Xlib-import qualified Graphics.X11.Xlib.Extras as XlibE+import qualified Graphics.X11.Xlib as Xlib+import qualified Graphics.X11.Xlib.Extras as XlibE -- | Information about window. You can inspect properties 'winInstance' -- and 'winClass' by @wmctrl@ command.@@ -45,16 +45,20 @@ -- > 0x02600003 0 totem.Totem mydesktop Movie Player -- -- In the above example, the third column shows @winInstance.winClass@.-data Window =- Window- { winInstance :: Text, -- ^ name of the application instance (part of @WM_CLASS@ property)- winClass :: Text, -- ^ name of the application class (part of @WM_CLASS@ property)- winName :: Text, -- ^ what's shown in the title bar- winID :: Xlib.Window- -- ^ X11 window ID.- --- -- @since 0.2.0.0- } deriving (Eq,Ord,Show)+data Window+ = Window+ { winInstance :: Text+ -- ^ name of the application instance (part of @WM_CLASS@ property)+ , winClass :: Text+ -- ^ name of the application class (part of @WM_CLASS@ property)+ , winName :: Text+ -- ^ what's shown in the title bar+ , winID :: Xlib.Window+ -- ^ X11 window ID.+ --+ -- @since 0.2.0.0+ }+ deriving (Eq, Ord, Show) -- | Use this type especially when the 'Window' is active. type ActiveWindow = Window@@ -93,7 +97,7 @@ feature <- Xlib.internAtom disp feature_str False result <- XlibE.getWindowProperty32 disp req (Xlib.defaultRootWindow disp) case result of- Nothing -> return False+ Nothing -> return False Just atoms -> return $ any ((feature ==) . fromIntegral) atoms -- | Get X11 Window handle for the active window. Port of libxdo's@@ -108,7 +112,7 @@ req <- liftIO $ Xlib.internAtom disp req_str False result <- MaybeT $ XlibE.getWindowProperty32 disp req (Xlib.defaultRootWindow disp) case result of- [] -> empty+ [] -> empty (val:_) -> return $ fromIntegral val xGetClassHint :: Xlib.Display -> Xlib.Window -> IO (Text, Text)
src/WildBind/X11/KeySym.hs view
@@ -7,365 +7,365 @@ -- -- @since 0.2.0.0 module WildBind.X11.KeySym- ( -- * The type- KeySym,- -- * Alphabet- xK_a,- xK_b,- xK_c,- xK_d,- xK_e,- xK_f,- xK_g,- xK_h,- xK_i,- xK_j,- xK_k,- xK_l,- xK_m,- xK_n,- xK_o,- xK_p,- xK_q,- xK_r,- xK_s,- xK_t,- xK_u,- xK_v,- xK_w,- xK_x,- xK_y,- xK_z,- xK_A,- xK_B,- xK_C,- xK_D,- xK_E,- xK_F,- xK_G,- xK_H,- xK_I,- xK_J,- xK_K,- xK_L,- xK_M,- xK_N,- xK_O,- xK_P,- xK_Q,- xK_R,- xK_S,- xK_T,- xK_U,- xK_V,- xK_W,- xK_X,- xK_Y,- xK_Z,- -- * Numbers- xK_0,- xK_1,- xK_2,- xK_3,- xK_4,- xK_5,- xK_6,- xK_7,- xK_8,- xK_9,- -- * ASCII symbols- xK_space,- xK_exclam,- xK_quotedbl,- xK_numbersign,- xK_dollar,- xK_percent,- xK_ampersand,- xK_apostrophe,- xK_quoteright,- xK_parenleft,- xK_parenright,- xK_asterisk,- xK_plus,- xK_comma,- xK_minus,- xK_period,- xK_slash,- xK_colon,- xK_semicolon,- xK_less,- xK_equal,- xK_greater,- xK_question,- xK_at,- xK_bracketleft,- xK_backslash,- xK_bracketright,- xK_asciicircum,- xK_underscore,- xK_grave,- xK_quoteleft,- xK_braceleft,- xK_bar,- xK_braceright,- xK_asciitilde,- -- * Control keys- xK_BackSpace,- xK_Tab,- xK_Linefeed,- xK_Clear,- xK_Return,- xK_Pause,- xK_Scroll_Lock,- xK_Sys_Req,- xK_Escape,- xK_Delete,- xK_Multi_key,- xK_Codeinput,- xK_SingleCandidate,- xK_MultipleCandidate,- xK_PreviousCandidate,- xK_Home,- xK_Left,- xK_Up,- xK_Right,- xK_Down,- xK_Prior,- xK_Page_Up,- xK_Next,- xK_Page_Down,- xK_End,- xK_Begin,- xK_Select,- xK_Print,- xK_Execute,- xK_Insert,- xK_Undo,- xK_Redo,- xK_Menu,- xK_Find,- xK_Cancel,- xK_Help,- xK_Break,- xK_Mode_switch,- xK_script_switch,- xK_Num_Lock,- -- * Number pad keys- xK_KP_Space,- xK_KP_Tab,- xK_KP_Enter,- xK_KP_F1,- xK_KP_F2,- xK_KP_F3,- xK_KP_F4,- xK_KP_Home,- xK_KP_Left,- xK_KP_Up,- xK_KP_Right,- xK_KP_Down,- xK_KP_Prior,- xK_KP_Page_Up,- xK_KP_Next,- xK_KP_Page_Down,- xK_KP_End,- xK_KP_Begin,- xK_KP_Insert,- xK_KP_Delete,- xK_KP_Equal,- xK_KP_Multiply,- xK_KP_Add,- xK_KP_Separator,- xK_KP_Subtract,- xK_KP_Decimal,- xK_KP_Divide,- xK_KP_0,- xK_KP_1,- xK_KP_2,- xK_KP_3,- xK_KP_4,- xK_KP_5,- xK_KP_6,- xK_KP_7,- xK_KP_8,- xK_KP_9,- -- * Function keys- xK_F1,- xK_F2,- xK_F3,- xK_F4,- xK_F5,- xK_F6,- xK_F7,- xK_F8,- xK_F9,- xK_F10,- xK_F11,- xK_L1,- xK_F12,- xK_L2,- xK_F13,- xK_L3,- xK_F14,- xK_L4,- xK_F15,- xK_L5,- xK_F16,- xK_L6,- xK_F17,- xK_L7,- xK_F18,- xK_L8,- xK_F19,- xK_L9,- xK_F20,- xK_L10,- xK_F21,- xK_R1,- xK_F22,- xK_R2,- xK_F23,- xK_R3,- xK_F24,- xK_R4,- xK_F25,- xK_R5,- xK_F26,- xK_R6,- xK_F27,- xK_R7,- xK_F28,- xK_R8,- xK_F29,- xK_R9,- xK_F30,- xK_R10,- xK_F31,- xK_R11,- xK_F32,- xK_R12,- xK_F33,- xK_R13,- xK_F34,- xK_R14,- xK_F35,- xK_R15,- -- * Modifier keys- xK_Shift_L,- xK_Shift_R,- xK_Control_L,- xK_Control_R,- xK_Caps_Lock,- xK_Shift_Lock,- xK_Meta_L,- xK_Meta_R,- xK_Alt_L,- xK_Alt_R,- xK_Super_L,- xK_Super_R,- xK_Hyper_L,- xK_Hyper_R,- -- * Alphabet with accent and ligatures- xK_Agrave,- xK_Aacute,- xK_Acircumflex,- xK_Atilde,- xK_Adiaeresis,- xK_Aring,- xK_AE,- xK_Ccedilla,- xK_Egrave,- xK_Eacute,- xK_Ecircumflex,- xK_Ediaeresis,- xK_Igrave,- xK_Iacute,- xK_Icircumflex,- xK_Idiaeresis,- xK_ETH,- xK_Eth,- xK_Ntilde,- xK_Ograve,- xK_Oacute,- xK_Ocircumflex,- xK_Otilde,- xK_Odiaeresis,- xK_multiply,- xK_Ooblique,- xK_Ugrave,- xK_Uacute,- xK_Ucircumflex,- xK_Udiaeresis,- xK_Yacute,- xK_THORN,- xK_Thorn,- xK_ssharp,- xK_agrave,- xK_aacute,- xK_acircumflex,- xK_atilde,- xK_adiaeresis,- xK_aring,- xK_ae,- xK_ccedilla,- xK_egrave,- xK_eacute,- xK_ecircumflex,- xK_ediaeresis,- xK_igrave,- xK_iacute,- xK_icircumflex,- xK_idiaeresis,- xK_eth,- xK_ntilde,- xK_ograve,- xK_oacute,- xK_ocircumflex,- xK_otilde,- xK_odiaeresis,- xK_division,- xK_oslash,- xK_ugrave,- xK_uacute,- xK_ucircumflex,- xK_udiaeresis,- xK_yacute,- xK_thorn,- xK_ydiaeresis,- -- * Other symbols- xK_nobreakspace,- xK_exclamdown,- xK_cent,- xK_sterling,- xK_currency,- xK_yen,- xK_brokenbar,- xK_section,- xK_diaeresis,- xK_copyright,- xK_ordfeminine,- xK_guillemotleft,- xK_notsign,- xK_hyphen,- xK_registered,- xK_macron,- xK_degree,- xK_plusminus,- xK_twosuperior,- xK_threesuperior,- xK_acute,- xK_mu,- xK_paragraph,- xK_periodcentered,- xK_cedilla,- xK_onesuperior,- xK_masculine,- xK_guillemotright,- xK_onequarter,- xK_onehalf,- xK_threequarters,- xK_questiondown,- -- * special keysym- xK_VoidSymbol,- ) where+ ( -- * The type+ KeySym+ -- * Alphabet+ , xK_a+ , xK_b+ , xK_c+ , xK_d+ , xK_e+ , xK_f+ , xK_g+ , xK_h+ , xK_i+ , xK_j+ , xK_k+ , xK_l+ , xK_m+ , xK_n+ , xK_o+ , xK_p+ , xK_q+ , xK_r+ , xK_s+ , xK_t+ , xK_u+ , xK_v+ , xK_w+ , xK_x+ , xK_y+ , xK_z+ , xK_A+ , xK_B+ , xK_C+ , xK_D+ , xK_E+ , xK_F+ , xK_G+ , xK_H+ , xK_I+ , xK_J+ , xK_K+ , xK_L+ , xK_M+ , xK_N+ , xK_O+ , xK_P+ , xK_Q+ , xK_R+ , xK_S+ , xK_T+ , xK_U+ , xK_V+ , xK_W+ , xK_X+ , xK_Y+ , xK_Z+ -- * Numbers+ , xK_0+ , xK_1+ , xK_2+ , xK_3+ , xK_4+ , xK_5+ , xK_6+ , xK_7+ , xK_8+ , xK_9+ -- * ASCII symbols+ , xK_space+ , xK_exclam+ , xK_quotedbl+ , xK_numbersign+ , xK_dollar+ , xK_percent+ , xK_ampersand+ , xK_apostrophe+ , xK_quoteright+ , xK_parenleft+ , xK_parenright+ , xK_asterisk+ , xK_plus+ , xK_comma+ , xK_minus+ , xK_period+ , xK_slash+ , xK_colon+ , xK_semicolon+ , xK_less+ , xK_equal+ , xK_greater+ , xK_question+ , xK_at+ , xK_bracketleft+ , xK_backslash+ , xK_bracketright+ , xK_asciicircum+ , xK_underscore+ , xK_grave+ , xK_quoteleft+ , xK_braceleft+ , xK_bar+ , xK_braceright+ , xK_asciitilde+ -- * Control keys+ , xK_BackSpace+ , xK_Tab+ , xK_Linefeed+ , xK_Clear+ , xK_Return+ , xK_Pause+ , xK_Scroll_Lock+ , xK_Sys_Req+ , xK_Escape+ , xK_Delete+ , xK_Multi_key+ , xK_Codeinput+ , xK_SingleCandidate+ , xK_MultipleCandidate+ , xK_PreviousCandidate+ , xK_Home+ , xK_Left+ , xK_Up+ , xK_Right+ , xK_Down+ , xK_Prior+ , xK_Page_Up+ , xK_Next+ , xK_Page_Down+ , xK_End+ , xK_Begin+ , xK_Select+ , xK_Print+ , xK_Execute+ , xK_Insert+ , xK_Undo+ , xK_Redo+ , xK_Menu+ , xK_Find+ , xK_Cancel+ , xK_Help+ , xK_Break+ , xK_Mode_switch+ , xK_script_switch+ , xK_Num_Lock+ -- * Number pad keys+ , xK_KP_Space+ , xK_KP_Tab+ , xK_KP_Enter+ , xK_KP_F1+ , xK_KP_F2+ , xK_KP_F3+ , xK_KP_F4+ , xK_KP_Home+ , xK_KP_Left+ , xK_KP_Up+ , xK_KP_Right+ , xK_KP_Down+ , xK_KP_Prior+ , xK_KP_Page_Up+ , xK_KP_Next+ , xK_KP_Page_Down+ , xK_KP_End+ , xK_KP_Begin+ , xK_KP_Insert+ , xK_KP_Delete+ , xK_KP_Equal+ , xK_KP_Multiply+ , xK_KP_Add+ , xK_KP_Separator+ , xK_KP_Subtract+ , xK_KP_Decimal+ , xK_KP_Divide+ , xK_KP_0+ , xK_KP_1+ , xK_KP_2+ , xK_KP_3+ , xK_KP_4+ , xK_KP_5+ , xK_KP_6+ , xK_KP_7+ , xK_KP_8+ , xK_KP_9+ -- * Function keys+ , xK_F1+ , xK_F2+ , xK_F3+ , xK_F4+ , xK_F5+ , xK_F6+ , xK_F7+ , xK_F8+ , xK_F9+ , xK_F10+ , xK_F11+ , xK_L1+ , xK_F12+ , xK_L2+ , xK_F13+ , xK_L3+ , xK_F14+ , xK_L4+ , xK_F15+ , xK_L5+ , xK_F16+ , xK_L6+ , xK_F17+ , xK_L7+ , xK_F18+ , xK_L8+ , xK_F19+ , xK_L9+ , xK_F20+ , xK_L10+ , xK_F21+ , xK_R1+ , xK_F22+ , xK_R2+ , xK_F23+ , xK_R3+ , xK_F24+ , xK_R4+ , xK_F25+ , xK_R5+ , xK_F26+ , xK_R6+ , xK_F27+ , xK_R7+ , xK_F28+ , xK_R8+ , xK_F29+ , xK_R9+ , xK_F30+ , xK_R10+ , xK_F31+ , xK_R11+ , xK_F32+ , xK_R12+ , xK_F33+ , xK_R13+ , xK_F34+ , xK_R14+ , xK_F35+ , xK_R15+ -- * Modifier keys+ , xK_Shift_L+ , xK_Shift_R+ , xK_Control_L+ , xK_Control_R+ , xK_Caps_Lock+ , xK_Shift_Lock+ , xK_Meta_L+ , xK_Meta_R+ , xK_Alt_L+ , xK_Alt_R+ , xK_Super_L+ , xK_Super_R+ , xK_Hyper_L+ , xK_Hyper_R+ -- * Alphabet with accent and ligatures+ , xK_Agrave+ , xK_Aacute+ , xK_Acircumflex+ , xK_Atilde+ , xK_Adiaeresis+ , xK_Aring+ , xK_AE+ , xK_Ccedilla+ , xK_Egrave+ , xK_Eacute+ , xK_Ecircumflex+ , xK_Ediaeresis+ , xK_Igrave+ , xK_Iacute+ , xK_Icircumflex+ , xK_Idiaeresis+ , xK_ETH+ , xK_Eth+ , xK_Ntilde+ , xK_Ograve+ , xK_Oacute+ , xK_Ocircumflex+ , xK_Otilde+ , xK_Odiaeresis+ , xK_multiply+ , xK_Ooblique+ , xK_Ugrave+ , xK_Uacute+ , xK_Ucircumflex+ , xK_Udiaeresis+ , xK_Yacute+ , xK_THORN+ , xK_Thorn+ , xK_ssharp+ , xK_agrave+ , xK_aacute+ , xK_acircumflex+ , xK_atilde+ , xK_adiaeresis+ , xK_aring+ , xK_ae+ , xK_ccedilla+ , xK_egrave+ , xK_eacute+ , xK_ecircumflex+ , xK_ediaeresis+ , xK_igrave+ , xK_iacute+ , xK_icircumflex+ , xK_idiaeresis+ , xK_eth+ , xK_ntilde+ , xK_ograve+ , xK_oacute+ , xK_ocircumflex+ , xK_otilde+ , xK_odiaeresis+ , xK_division+ , xK_oslash+ , xK_ugrave+ , xK_uacute+ , xK_ucircumflex+ , xK_udiaeresis+ , xK_yacute+ , xK_thorn+ , xK_ydiaeresis+ -- * Other symbols+ , xK_nobreakspace+ , xK_exclamdown+ , xK_cent+ , xK_sterling+ , xK_currency+ , xK_yen+ , xK_brokenbar+ , xK_section+ , xK_diaeresis+ , xK_copyright+ , xK_ordfeminine+ , xK_guillemotleft+ , xK_notsign+ , xK_hyphen+ , xK_registered+ , xK_macron+ , xK_degree+ , xK_plusminus+ , xK_twosuperior+ , xK_threesuperior+ , xK_acute+ , xK_mu+ , xK_paragraph+ , xK_periodcentered+ , xK_cedilla+ , xK_onesuperior+ , xK_masculine+ , xK_guillemotright+ , xK_onequarter+ , xK_onehalf+ , xK_threequarters+ , xK_questiondown+ -- * special keysym+ , xK_VoidSymbol+ ) where -import Graphics.X11.Xlib+import Graphics.X11.Xlib
test/WildBind/X11/EmulateSpec.hs view
@@ -1,27 +1,26 @@-module WildBind.X11.EmulateSpec (main,spec) where+module WildBind.X11.EmulateSpec+ ( main+ , spec+ ) where -import Control.Exception (bracket)-import Control.Monad (forM_)-import Control.Monad.Trans.Maybe (runMaybeT)-import Data.Bits ((.|.))-import Data.Text (unpack)-import qualified Graphics.X11.Xlib as Xlib-import Test.Hspec+import Control.Exception (bracket)+import Control.Monad (forM_)+import Control.Monad.Trans.Maybe (runMaybeT)+import Data.Bits ((.|.))+import Data.Text (unpack)+import qualified Graphics.X11.Xlib as Xlib+import Test.Hspec -import WildBind (frontNextEvent, FrontEvent(..))-import qualified WildBind.Description as WBD-import WildBind.X11- ( withX11Front, makeFrontEnd,- XMod(..), release, press,- defaultRootWindow,- XKeyEvent(..), KeyEventType(..),- alt, super, ctrl, shift- )-import WildBind.X11.Emulate (sendKeyTo)-import WildBind.X11.Internal.Key (xKeyEventToXKeyInput, getKeyMaskMap, KeyMaskMap)-import WildBind.X11.Internal.Window (fromWinID)+import WildBind (FrontEvent (..), frontNextEvent)+import qualified WildBind.Description as WBD+import WildBind.X11 (KeyEventType (..), XKeyEvent (..), XMod (..), alt,+ ctrl, defaultRootWindow, makeFrontEnd, press,+ release, shift, super, withX11Front)+import WildBind.X11.Emulate (sendKeyTo)+import WildBind.X11.Internal.Key (KeyMaskMap, getKeyMaskMap, xKeyEventToXKeyInput)+import WildBind.X11.Internal.Window (fromWinID) -import WildBind.X11.TestUtil (checkIfX11Available)+import WildBind.X11.TestUtil (checkIfX11Available) main :: IO () main = hspec spec@@ -33,7 +32,7 @@ press Xlib.xK_Right, release $ ctrl $ shift Xlib.xK_F12, ctrl $ alt Xlib.xK_3- + -- ctrl $ shift Xlib.xK_bracketleft ---- "Shift" modifier is tricky, because it affects@@ -103,4 +102,4 @@ unwrapMaybe = maybe error_convert id - +
test/WildBind/X11/Internal/NotificationDebouncerSpec.hs view
@@ -1,12 +1,14 @@-module WildBind.X11.Internal.NotificationDebouncerSpec (spec) where+module WildBind.X11.Internal.NotificationDebouncerSpec+ ( spec+ ) where -import Test.Hspec+import Test.Hspec -import qualified Graphics.X11.Xlib as Xlib-import qualified Graphics.X11.Xlib.Extras as XlibE+import qualified Graphics.X11.Xlib as Xlib+import qualified Graphics.X11.Xlib.Extras as XlibE import qualified WildBind.X11.Internal.NotificationDebouncer as Deb -import WildBind.X11.TestUtil (checkIfX11Available)+import WildBind.X11.TestUtil (checkIfX11Available) spec :: Spec spec = checkIfX11Available $ do@@ -21,7 +23,7 @@ -- showDisplay :: Xlib.Display -> String -- showDisplay disp = show disp ++ "(conn number = "++ show (Xlib.connectionNumber disp) ++")"- + waitForDebouncedEvent :: Deb.Debouncer -> Xlib.Display -> Xlib.XEventPtr -> IO Bool waitForDebouncedEvent deb disp xev = doit 0 where doit :: Int -> IO Bool
test/WildBind/X11/TestUtil.hs view
@@ -1,26 +1,26 @@ -- | -- Module: WildBind.X11.TestUtil--- Description: +-- Description: -- Maintainer: Toshio Ito <debug.ito@gmail.com> ----- +-- module WildBind.X11.TestUtil- ( checkIfX11Available,- withGrabs- ) where+ ( checkIfX11Available+ , withGrabs+ ) where -import Control.Exception (bracket)-import Control.Monad (when)-import Control.Applicative ((<$>))-import System.Environment (lookupEnv)-import Test.Hspec+import Control.Applicative ((<$>))+import Control.Exception (bracket)+import Control.Monad (when)+import System.Environment (lookupEnv)+import Test.Hspec -import WildBind (FrontEnd(..))+import WildBind (FrontEnd (..)) isDisplaySet :: IO Bool isDisplaySet = exists <$> lookupEnv "DISPLAY" where exists (Just v) = v /= ""- exists _ = False+ exists _ = False checkIfX11Available :: Spec -> Spec checkIfX11Available = before $ do
test/WildBind/X11Spec.hs view
@@ -1,40 +1,43 @@-{-# LANGUAGE FlexibleContexts, CPP, OverloadedStrings #-}-module WildBind.X11Spec (main, spec) where+{-# LANGUAGE CPP #-}+{-# LANGUAGE FlexibleContexts #-}+{-# LANGUAGE OverloadedStrings #-}+module WildBind.X11Spec+ ( main+ , spec+ ) where -import Control.Applicative ((<$>))-import Control.Concurrent.Async (async, waitCatch)-import Control.Exception (finally, Exception(fromException), throwIO)-import Control.Monad (forM_)-import Control.Monad.IO.Class (liftIO)+import Control.Applicative ((<$>))+import Control.Concurrent.Async (async, waitCatch)+import Control.Exception (Exception (fromException), finally, throwIO)+import Control.Monad (forM_)+import Control.Monad.IO.Class (liftIO) import qualified Control.Monad.Trans.State as State-import Data.Monoid ((<>))-import Data.List (intercalate, reverse)-import Data.IORef (IORef, newIORef, readIORef, modifyIORef)-import Data.Text (unpack)-import Data.Time.Clock (getCurrentTime, diffUTCTime)-import qualified Graphics.X11.Xlib as Xlib-import System.IO (hPutStrLn,stderr)-import Test.Hspec+import Data.IORef (IORef, modifyIORef, newIORef, readIORef)+import Data.List (intercalate, reverse)+import Data.Monoid ((<>))+import Data.Text (unpack)+import Data.Time.Clock (diffUTCTime, getCurrentTime)+import qualified Graphics.X11.Xlib as Xlib+import System.IO (hPutStrLn, stderr)+import Test.Hspec -import WildBind- ( FrontEnd(frontSetGrab, frontUnsetGrab, frontNextEvent),- FrontEvent(FEChange,FEInput), Describable, ActionDescription,- Option(..), defOption, wildBind',- binds', startFrom, on, as, run, whenBack, revise, justBefore- )-import qualified WildBind.Description as WBD-import qualified WildBind.Input.NumPad as NumPad-import WildBind.X11- ( withFrontEnd, ActiveWindow, XKeyInput,- XMod(..), XKeyEvent(..), KeyEventType(..),- ctrl, alt, super, shift, release, press- )-import qualified WildBind.X11.KeySym as WKS+import WildBind (ActionDescription, Describable,+ FrontEnd (frontNextEvent, frontSetGrab, frontUnsetGrab),+ FrontEvent (FEChange, FEInput), Option (..), as, binds',+ defOption, justBefore, on, revise, run, startFrom,+ whenBack, wildBind')+import qualified WildBind.Description as WBD+import qualified WildBind.Input.NumPad as NumPad+import WildBind.X11 (ActiveWindow, KeyEventType (..), XKeyEvent (..),+ XKeyInput, XMod (..), alt, ctrl, press, release, shift,+ super, withFrontEnd)+import qualified WildBind.X11.KeySym as WKS -import WildBind.X11.TestUtil (checkIfX11Available, withGrabs)+import WildBind.X11.TestUtil (checkIfX11Available, withGrabs) -newtype MyException = MyException String- deriving (Show,Eq,Ord)+newtype MyException+ = MyException String+ deriving (Eq, Ord, Show) instance Exception MyException @@ -100,7 +103,7 @@ time `shouldSatisfy` (< 500) case ev of FEChange _ -> return ()- _ -> expectationFailure ("FEChange is expected, but got " ++ show ev)+ _ -> expectationFailure ("FEChange is expected, but got " ++ show ev) it "should NOT throw exception when it tries to double-grab in the same process" $ withFrontEnd $ \f1 -> withFrontEnd $ \f2 -> do frontSetGrab f1 NumPad.NumLeft `shouldReturn` ()@@ -131,8 +134,8 @@ forM_ (zip got_descs exp_descs) $ uncurry shouldMatchList case result of Right _ -> expectationFailure "expects an exception, but nothing happened."- Left e -> fromException e `shouldBe` (Just $ MyException "OK")- + Left e -> fromException e `shouldBe` (Just $ MyException "OK")+ describe "X11Front - NumPadUnlocked" $ do it "should grab/ungrab keys" $ maybeRun $ withFrontEndForTest $ \f -> do let grabCase' :: FrontEnd ActiveWindow NumPad.NumPadUnlocked -> Expectation
wild-bind-x11.cabal view
@@ -1,5 +1,5 @@ name: wild-bind-x11-version: 0.2.0.14+version: 0.2.0.15 author: Toshio Ito <debug.ito@gmail.com> maintainer: Toshio Ito <debug.ito@gmail.com> license: BSD3@@ -28,7 +28,7 @@ WildBind.X11.Internal.NotificationDebouncer other-modules: WildBind.X11.Internal.FrontEnd, WildBind.X11.Internal.GrabMan- build-depends: base >=4.6 && <4.16,+ build-depends: base >=4.6 && <4.17, wild-bind >=0.1.0 && <0.2, text >=1.2.0 && <1.3, X11 >=1.6.1 && <1.11,@@ -69,7 +69,7 @@ build-depends: base, wild-bind-x11, wild-bind, X11, text, transformers, hspec >=2.1.7,- time >=1.5.0 && <1.10,+ time >=1.5.0 && <1.12, async >=2.0.2 && <2.3 source-repository head