Output: add setDisplayBounds field and implementation for TerminfoBased backend

This commit is contained in:
Jonathan Daugherty 2020-07-15 13:49:05 -07:00
parent 5922c53459
commit 6a9c90da0e
5 changed files with 24 additions and 0 deletions

View File

@ -7,3 +7,12 @@ unsigned long vty_c_get_window_size(int fd) {
else else
return 0x190050; return 0x190050;
} }
void vty_c_set_window_size(int fd, unsigned long val) {
struct winsize w;
if (ioctl(fd, TIOCGWINSZ, &w) >= 0) {
w.ws_row = val >> 16;
w.ws_col = val & 0xFFFF;
ioctl(fd, TIOCSWINSZ, &w);
}
}

View File

@ -1 +1,2 @@
unsigned long vty_c_get_window_size(void); unsigned long vty_c_get_window_size(void);
unsigned long vty_c_set_window_size(int fd, unsigned long val);

View File

@ -73,6 +73,8 @@ data Output = Output
-- | Return the display to the state before `reserveDisplay` If no -- | Return the display to the state before `reserveDisplay` If no
-- previous state then set the display state to the initial state. -- previous state then set the display state to the initial state.
, releaseDisplay :: IO () , releaseDisplay :: IO ()
-- | Sets the current display bounds (width, height).
, setDisplayBounds :: (Int, Int) -> IO ()
-- | Returns the current display bounds. -- | Returns the current display bounds.
, displayBounds :: IO DisplayRegion , displayBounds :: IO DisplayRegion
-- | Output the bytestring to the terminal device. -- | Output the bytestring to the terminal device.

View File

@ -48,6 +48,7 @@ mockTerminal r = liftIO $ do
, releaseDisplay = return () , releaseDisplay = return ()
, ringTerminalBell = return () , ringTerminalBell = return ()
, supportsBell = return False , supportsBell = return False
, setDisplayBounds = const $ return ()
, displayBounds = return r , displayBounds = return r
, outputByteBuffer = \bytes -> do , outputByteBuffer = \bytes -> do
putStrLn $ "mock outputByteBuffer of " ++ show (BS.length bytes) ++ " bytes" putStrLn $ "mock outputByteBuffer of " ++ show (BS.length bytes) ++ " bytes"

View File

@ -10,10 +10,12 @@
-- Copyright Corey O'Connor (coreyoconnor@gmail.com) -- Copyright Corey O'Connor (coreyoconnor@gmail.com)
module Graphics.Vty.Output.TerminfoBased module Graphics.Vty.Output.TerminfoBased
( reserveTerminal ( reserveTerminal
, setWindowSize
) )
where where
import Control.Monad (when) import Control.Monad (when)
import Data.Bits (shiftL)
import qualified Data.ByteString as BS import qualified Data.ByteString as BS
import Data.ByteString.Internal (toForeignPtr) import Data.ByteString.Internal (toForeignPtr)
import Data.Terminfo.Parse import Data.Terminfo.Parse
@ -174,6 +176,8 @@ reserveTerminal termName outFd = do
, releaseDisplay = do , releaseDisplay = do
maybeSendCap rmcup [] maybeSendCap rmcup []
maybeSendCap cnorm [] maybeSendCap cnorm []
, setDisplayBounds = \(w, h) ->
setWindowSize outFd (w, h)
, displayBounds = do , displayBounds = do
rawSize <- getWindowSize outFd rawSize <- getWindowSize outFd
case rawSize of case rawSize of
@ -244,6 +248,13 @@ getWindowSize fd = do
(a,b) <- (`divMod` 65536) `fmap` c_getWindowSize fd (a,b) <- (`divMod` 65536) `fmap` c_getWindowSize fd
return (fromIntegral b, fromIntegral a) return (fromIntegral b, fromIntegral a)
foreign import ccall "gwinsz.h vty_c_set_window_size" c_setWindowSize :: Fd -> CLong -> IO ()
setWindowSize :: Fd -> (Int, Int) -> IO ()
setWindowSize fd (w, h) = do
let val = (h `shiftL` 16) + w
c_setWindowSize fd $ fromIntegral val
terminfoDisplayContext :: Output -> TerminfoCaps -> DisplayRegion -> IO DisplayContext terminfoDisplayContext :: Output -> TerminfoCaps -> DisplayRegion -> IO DisplayContext
terminfoDisplayContext tActual terminfoCaps r = return dc terminfoDisplayContext tActual terminfoCaps r = return dc
where dc = DisplayContext where dc = DisplayContext