packages feed

brillo-1.13.3: Brillo/Internals/Interface/Backend/Types.hs

{-# OPTIONS -fspec-constr-count=5 #-}
{-# LANGUAGE Rank2Types #-}

module Brillo.Internals.Interface.Backend.Types (
  module Brillo.Internals.Interface.Backend.Types,
  module Brillo.Data.Display,
)
where

import Brillo.Data.Display
import Data.IORef


{-| The functions every backend window managed backend needs to support.

  The Backend module interfaces with the window manager, and handles opening
  and closing the window, and managing key events etc.

  It doesn't know anything about drawing lines or setting colors.
  When we get a display callback, Brillo will perform OpenGL actions, and
  the backend needs to have OpenGL in a state where it's able to accept them.
-}
class Backend a where
  -- | Initialize the state used by the backend.
  -- If you don't use any state, make a Unit-like type.
  initBackendState :: a


  -- | Perform any initialization that needs to happen before opening a window
  --   The Boolean flag indicates if any debug information should be printed to
  --   the terminal
  initializeBackend :: IORef a -> Bool -> IO ()


  -- | Perform any deinitialization and close the backend.
  exitBackend :: IORef a -> IO ()


  -- | Open a window with the given display mode.
  openWindow :: IORef a -> Display -> IO ()


  -- | Dump information about the backend to the terminal.
  dumpBackendState :: IORef a -> IO ()


  -- | Install the display callbacks.
  installDisplayCallback :: IORef a -> [Callback] -> IO ()


  -- | Install the window close callback.
  installWindowCloseCallback :: IORef a -> IO ()


  -- | Install the reshape callbacks.
  installReshapeCallback :: IORef a -> [Callback] -> IO ()


  -- | Install the keymouse press callbacks.
  installKeyMouseCallback :: IORef a -> [Callback] -> IO ()


  -- | Install the mouse motion callbacks.
  installMotionCallback :: IORef a -> [Callback] -> IO ()


  -- | Install the idle callbacks.
  installIdleCallback :: IORef a -> [Callback] -> IO ()


  -- | The mainloop of the backend.
  runMainLoop :: IORef a -> IO ()


  -- | A function that signals that screen has to be updated.
  postRedisplay :: IORef a -> IO ()


  -- | Function that returns (width,height) of the window in pixels.
  getWindowDimensions :: IORef a -> IO (Int, Int)


  -- | Function that returns (width,height) of a fullscreen window in pixels.
  getScreenSize :: IORef a -> IO (Int, Int)


  -- | Function that reports the time elapsed since the application started.
  --   (in seconds)
  elapsedTime :: IORef a -> IO Double


  -- | Function that puts the current thread to sleep for 'n' seconds.
  sleep :: IORef a -> Double -> IO ()


-- The callbacks should work for all backends. We pass a reference to the
-- backend state so that the callbacks have access to the class dictionary and
-- can thus call the appropriate backend functions.

-- | Display callback has no arguments.
type DisplayCallback =
  forall a. (Backend a) => IORef a -> IO ()


-- | Arguments: KeyType, Key Up \/ Down, Ctrl \/ Alt \/ Shift pressed, latest mouse location.
type KeyboardMouseCallback =
  forall a. (Backend a) => IORef a -> Key -> KeyState -> Modifiers -> (Int, Int) -> IO ()


-- | Arguments: (PosX,PosY) in pixels.
type MotionCallback =
  forall a. (Backend a) => IORef a -> (Int, Int) -> IO ()


-- | No arguments.
type IdleCallback =
  forall a. (Backend a) => IORef a -> IO ()


-- | Arguments: (Width,Height) in pixels.
type ReshapeCallback =
  forall a. (Backend a) => IORef a -> (Int, Int) -> IO ()


-------------------------------------------------------------------------------
data Callback
  = Display DisplayCallback
  | KeyMouse KeyboardMouseCallback
  | Idle IdleCallback
  | Motion MotionCallback
  | Reshape ReshapeCallback


-- | Check if this is an `Idle` callback.
isIdleCallback :: Callback -> Bool
isIdleCallback cc =
  case cc of
    Idle _ -> True
    _ -> False


-------------------------------------------------------------------------------
-- This is Brillo's view of mouse and keyboard events.
-- The actual events provided by the backends are converted to this form
-- by the backend module.

data Key
  = Char Char
  | SpecialKey SpecialKey
  | MouseButton MouseButton
  deriving (Show, Eq, Ord)


data MouseButton
  = LeftButton
  | MiddleButton
  | RightButton
  | WheelUp
  | WheelDown
  | AdditionalButton Int
  deriving (Show, Eq, Ord)


data KeyState
  = Down
  | Up
  deriving (Show, Eq, Ord)


data SpecialKey
  = KeyUnknown
  | KeySpace
  | KeyEsc
  | KeyF1
  | KeyF2
  | KeyF3
  | KeyF4
  | KeyF5
  | KeyF6
  | KeyF7
  | KeyF8
  | KeyF9
  | KeyF10
  | KeyF11
  | KeyF12
  | KeyF13
  | KeyF14
  | KeyF15
  | KeyF16
  | KeyF17
  | KeyF18
  | KeyF19
  | KeyF20
  | KeyF21
  | KeyF22
  | KeyF23
  | KeyF24
  | KeyF25
  | KeyUp
  | KeyDown
  | KeyLeft
  | KeyRight
  | KeyTab
  | KeyEnter
  | KeyBackspace
  | KeyInsert
  | KeyNumLock
  | KeyBegin
  | KeyDelete
  | KeyPageUp
  | KeyPageDown
  | KeyHome
  | KeyEnd
  | KeyShiftL
  | KeyShiftR
  | KeyCtrlL
  | KeyCtrlR
  | KeyAltL
  | KeyAltR
  | KeyPad0
  | KeyPad1
  | KeyPad2
  | KeyPad3
  | KeyPad4
  | KeyPad5
  | KeyPad6
  | KeyPad7
  | KeyPad8
  | KeyPad9
  | KeyPadDivide
  | KeyPadMultiply
  | KeyPadSubtract
  | KeyPadAdd
  | KeyPadDecimal
  | KeyPadEqual
  | KeyPadEnter
  deriving (Show, Eq, Ord)


data Modifiers
  = Modifiers
  { shift :: KeyState
  , ctrl :: KeyState
  , alt :: KeyState
  }
  deriving (Show, Eq, Ord)