on master help sign in
Mouse: support Normal mode events in terminals with a "screen" terminal type
82432dbJonathan Daugherty
src/Graphics/Vty/Input/Classify.hs+1
@@ -57,6 +57,7 @@ classify table =
57 let standardClassifier = compile table
57 let standardClassifier = compile table
58 in \s -> case s of
58 in \s -> case s of
59 ('\ESC':'[':'<':cs) | length cs >= 6 -> classifySGRMouseEvent cs
59 ('\ESC':'[':'<':cs) | length cs >= 6 -> classifySGRMouseEvent cs
60+ ('\ESC':'[':'M':cs) | length cs >= 3 -> classifyNormalMouseEvent cs
60 c:cs | ord c >= 0xC2 -> classifyUtf8 c cs
61 c:cs | ord c >= 0xC2 -> classifyUtf8 c cs
61 _ -> standardClassifier s
62 _ -> standardClassifier s
62
63
src/Graphics/Vty/Input/Events.hs+1−1
@@ -32,7 +32,7 @@ data Event
32 = EvKey Key [Modifier]
32 = EvKey Key [Modifier]
33 -- | \todo mouse events are not supported
33 -- | \todo mouse events are not supported
34 | EvMouseDown Int Int Button [Modifier]
34 | EvMouseDown Int Int Button [Modifier]
35− | EvMouseUp Int Int Button
35+ | EvMouseUp Int Int (Maybe Button)
36 -- | if read from 'eventChannel' this is the size at the time of the signal. If read from
36 -- | if read from 'eventChannel' this is the size at the time of the signal. If read from
37 -- 'nextEvent' this is the size at the time the event was processed by Vty. Typically these are
37 -- 'nextEvent' this is the size at the time the event was processed by Vty. Typically these are
38 -- the same, but if somebody is resizing the terminal quickly they can be different.
38 -- the same, but if somebody is resizing the terminal quickly they can be different.
src/Graphics/Vty/Input/Mouse.hs+26−4
@@ -2,6 +2,7 @@ module Graphics.Vty.Input.Mouse
2 ( requestSGRMouseEvents
2 ( requestSGRMouseEvents
3 , disableSGRMouseEvents
3 , disableSGRMouseEvents
4 , classifySGRMouseEvent
4 , classifySGRMouseEvent
5+ , classifyNormalMouseEvent
5 ) where
6 ) where
6
7
7import Graphics.Vty.Input.Events
8import Graphics.Vty.Input.Events
@@ -63,8 +64,8 @@ hasBitSet :: Int -> Int -> Bool
63hasBitSet val bit = val .&. bit > 0
64hasBitSet val bit = val .&. bit > 0
64
65
65-- Given a modifer/button value, determine which button was indicated
66-- Given a modifer/button value, determine which button was indicated
66−getButton :: Int -> Parser Button
67+getSGRButton :: Int -> Parser Button
67−getButton mods =
68+getSGRButton mods =
68 let buttonMap = [ (leftButton, BLeft)
69 let buttonMap = [ (leftButton, BLeft)
69 , (middleButton, BMiddle)
70 , (middleButton, BMiddle)
70 , (rightButton, BRight)
71 , (rightButton, BRight)
@@ -112,6 +113,27 @@ expectChar c = do
112 c' <- readChar
113 c' <- readChar
113 if c' == c then return () else failParse
114 if c' == c then return () else failParse
114
115
116+-- Attempt to classify a control sequence as a "normal" mouse event. To
117+-- get here we should have already read "\ESC[M" so that will not be
118+-- included in the string to be parsed.
119+classifyNormalMouseEvent :: [Char] -> KClass
120+classifyNormalMouseEvent s = runParser s $ do
121+ statusChar <- readChar
122+ xCoordChar <- readChar
123+ yCoordChar <- readChar
124+
125+ let xCoord = fromEnum xCoordChar - 32
126+ yCoord = fromEnum yCoordChar - 32
127+ status = fromEnum statusChar
128+ modifiers = getModifiers status
129+
130+ let press = status .&. buttonMask /= 3
131+ case press of
132+ True -> do
133+ button <- getSGRButton status
134+ return $ EvMouseDown xCoord yCoord button modifiers
135+ False -> return $ EvMouseUp xCoord yCoord Nothing
136+
115-- Attempt to classify a control sequence as an SGR mouse event. To
137-- Attempt to classify a control sequence as an SGR mouse event. To
116-- get here we should have already read "\ESC[<" so that will not be
138-- get here we should have already read "\ESC[<" so that will not be
117-- included in the string to be parsed.
139-- included in the string to be parsed.
@@ -125,8 +147,8 @@ classifySGRMouseEvent s = runParser s $ do
125 final <- readChar
147 final <- readChar
126
148
127 let modifiers = getModifiers mods
149 let modifiers = getModifiers mods
128− button <- getButton mods
150+ button <- getSGRButton mods
129 case final of
151 case final of
130 'M' -> return $ EvMouseDown xCoord yCoord button modifiers
152 'M' -> return $ EvMouseDown xCoord yCoord button modifiers
131− 'm' -> return $ EvMouseUp xCoord yCoord button
153+ 'm' -> return $ EvMouseUp xCoord yCoord (Just button)
132 _ -> failParse
154 _ -> failParse
src/Graphics/Vty/Output.hs+1−1
@@ -61,7 +61,7 @@ import Data.Monoid ((<>))
61-- with only what is provided in the haskell platform. Use ansi-terminal
61-- with only what is provided in the haskell platform. Use ansi-terminal
62outputForConfig :: Config -> IO Output
62outputForConfig :: Config -> IO Output
63outputForConfig Config{ outputFd = Just fd, termName = Just termName, .. } = do
63outputForConfig Config{ outputFd = Just fd, termName = Just termName, .. } = do
64− t <- if "xterm" `isPrefixOf` termName
64+ t <- if "xterm" `isPrefixOf` termName || "screen" `isPrefixOf` termName
65 then XTermColor.reserveTerminal termName fd
65 then XTermColor.reserveTerminal termName fd
66 -- Not an xterm-like terminal. try for generic terminfo.
66 -- Not an xterm-like terminal. try for generic terminfo.
67 else TerminfoBased.reserveTerminal termName fd
67 else TerminfoBased.reserveTerminal termName fd