aboutsummaryrefslogtreecommitdiff
path: root/src/Rahm/Desktop/Submap.hs
diff options
context:
space:
mode:
authorJosh Rahm <rahm@google.com>2023-12-13 12:01:31 -0700
committerJosh Rahm <rahm@google.com>2023-12-13 12:03:16 -0700
commit4cdab9f06cd0ecf5ad7d5ee15dd83c4dc4eb396a (patch)
tree792b639c8b9024e0d05827df27523fac6d897c79 /src/Rahm/Desktop/Submap.hs
parent7c16c50990492f9e6cc2477f8284dc1a2f33d946 (diff)
downloadrde-4cdab9f06cd0ecf5ad7d5ee15dd83c4dc4eb396a.tar.gz
rde-4cdab9f06cd0ecf5ad7d5ee15dd83c4dc4eb396a.tar.bz2
rde-4cdab9f06cd0ecf5ad7d5ee15dd83c4dc4eb396a.zip
Replacing existing binder DSL with a better and more expressive DSL.
This new DSL is cleaner and more powerful. This new DSL allows mixing key and mouse bindings in submappings, which can be very useful.
Diffstat (limited to 'src/Rahm/Desktop/Submap.hs')
-rw-r--r--src/Rahm/Desktop/Submap.hs78
1 files changed, 78 insertions, 0 deletions
diff --git a/src/Rahm/Desktop/Submap.hs b/src/Rahm/Desktop/Submap.hs
index b705a24..9c20381 100644
--- a/src/Rahm/Desktop/Submap.hs
+++ b/src/Rahm/Desktop/Submap.hs
@@ -8,19 +8,28 @@ module Rahm.Desktop.Submap
submap,
submapDefault,
submapDefaultWithKey,
+ ButtonOrKeyEvent (..),
+ nextButtonOrKeyEvent,
+ getStringForKey,
escape,
)
where
import Control.Concurrent (threadDelay)
+import Control.Exception (SomeException (SomeException), catch)
+import Control.Monad (when)
import Control.Monad.Fix (fix)
import Control.Monad.Trans (MonadTrans (lift))
import Control.Monad.Trans.Maybe (MaybeT (MaybeT))
+import Data.Aeson (Result (Error))
+import Data.Bits ((.&.))
+import Data.Char (toUpper)
import Data.Map (Map)
import qualified Data.Map as Map (findWithDefault, lookup)
import Data.Time.Clock.POSIX (getPOSIXTime)
import Data.Word (Word64)
import Rahm.Desktop.Common (pointerWindow, runMaybeT_)
+import Rahm.Desktop.Logger (logs)
import XMonad
( Button,
ButtonMask,
@@ -37,6 +46,7 @@ import XMonad
XEventPtr,
allocaXEvent,
asKeyEvent,
+ asks,
buttonPressMask,
checkMaskEvent,
cleanMask,
@@ -49,14 +59,19 @@ import XMonad
isModifierKey,
keyPressMask,
keycodeToKeysym,
+ keysymToKeycode,
+ keysymToString,
lookupString,
maskEvent,
pointerMotionMask,
+ setKeyEvent,
+ shiftMask,
ungrabKeyboard,
ungrabPointer,
(.|.),
)
import qualified XMonad.Util.ExtensibleState as XS
+import XMonad.Util.Loggers (logSp)
newtype Escape = Escape Bool
@@ -98,6 +113,51 @@ getMaskEventWithTimeout timeout d mask fn = do
then return True
else threadDelay 1000 >> getMaskEventWithTimeout' ptr timeout
+data ButtonOrKeyEvent
+ = ButtonPress
+ { event_mask :: KeyMask,
+ event_button :: Button
+ }
+ | KeyPress
+ { event_mask :: KeyMask,
+ event_keysym :: KeySym,
+ event_string :: String
+ }
+
+nextButtonOrKeyEvent :: MaybeT X ButtonOrKeyEvent
+nextButtonOrKeyEvent = do
+ b <- lift getEscape
+ when b (MaybeT (return Nothing))
+
+ XConf {theRoot = root, display = d} <- ask
+ io $ do
+ grabKeyboard d root False grabModeAsync grabModeAsync currentTime
+ grabPointer d root False buttonPressMask grabModeAsync grabModeAsync 0 0 currentTime
+
+ ret <- MaybeT $
+ io $
+ fix $ \tryAgain -> do
+ ret <-
+ getMaskEventWithTimeout 5000 d (keyPressMask .|. buttonPressMask) $ \p -> do
+ ev <- getEvent p
+ case ev of
+ ButtonEvent {ev_button = b, ev_state = m} ->
+ return $ ButtonPress m b
+ KeyEvent {ev_keycode = code, ev_state = m} -> do
+ keysym <- keycodeToKeysym d code 0
+ (_, str) <- lookupString (asKeyEvent p)
+ return $ KeyPress m keysym str
+ case ret of
+ Just (KeyPress m sym str) | isModifierKey sym -> tryAgain
+ x -> return x
+
+ io $ do
+ ungrabKeyboard d currentTime
+ ungrabPointer d currentTime
+
+ m' <- lift $ cleanMask (event_mask ret)
+ return ret {event_mask = m'}
+
{-
- Like submap fram XMonad.Actions.Submap, but sends the string from
- XLookupString to the function along side the keysym.
@@ -134,6 +194,24 @@ mapNextStringWithKeysym fn = do
m <- lift $ cleanMask m'
fn m keysym str
+-- getStringForKey :: (KeyMask, KeySym) -> X String
+-- getStringForKey (m, sym) = do
+-- d <- asks display
+-- io $
+-- allocaXEvent
+-- ( \xev -> do
+-- kc <- keysymToKeycode d sym
+-- setKeyEvent xev 0 0 0 m kc False
+-- (_, str) <- lookupString (asKeyEvent xev)
+-- return str
+-- )
+-- `catch` ( \e -> do
+-- putStrLn $ "Error in getStringForKey: " ++ show (e :: SomeException)
+-- return "?"
+-- )
+getStringForKey :: (KeyMask, KeySym) -> String
+getStringForKey (m, sym) = (if (m .&. shiftMask) /= 0 then map toUpper else id) (keysymToString sym)
+
{- Like submap, but on the character typed rather than the kysym. -}
mapNextString :: (KeyMask -> String -> MaybeT X a) -> MaybeT X a
mapNextString fn = mapNextStringWithKeysym (\m _ s -> fn m s)