{-# LANGUAGE MultiWayIf #-}

module Mischief.SDL.Events
  ( -- $intro
    SDLEventsPlugin,
    SDLMessage (..),
    SDLWindow (..),
    handleEvents,
  )
where

import Control.Monad
import Control.Monad.IO.Class
import Data.Foldable
import Data.Primitive.Ptr
import Foreign (Storable (peek), castPtr)
import Mischief.ECS
import Mischief.ECS.App.Schedules (First)
import Mischief.ECS.Foreign as F
import Mischief.ECS.Messages (Message)
import Mischief.ECS.Messages qualified as Messages
import SDL3.Sys (destroyWindow)
import SDL3.Sys qualified as SDL3
import System.Exit

newtype SDLWindow = SDLWindow {SDLWindow -> Ptr SDL_Window
ptr :: Ptr SDL3.SDL_Window}
  deriving anyclass (Typeable SDLWindow
[HookRel SDLWindow]
[Hook SDLWindow]
Set DefaultComponentType
IsExclusive (IsExclusiveRel SDLWindow)
(Typeable SDLWindow, IsExclusive (IsExclusiveRel SDLWindow)) =>
Set DefaultComponentType
-> [Hook SDLWindow]
-> [Hook SDLWindow]
-> [Hook SDLWindow]
-> [HookRel SDLWindow]
-> [HookRel SDLWindow]
-> [HookRel SDLWindow]
-> Component SDLWindow
forall c.
(Typeable c, IsExclusive (IsExclusiveRel c)) =>
Set DefaultComponentType
-> [Hook c]
-> [Hook c]
-> [Hook c]
-> [HookRel c]
-> [HookRel c]
-> [HookRel c]
-> Component c
$crequired :: Set DefaultComponentType
required :: Set DefaultComponentType
$conAdd :: [Hook SDLWindow]
onAdd :: [Hook SDLWindow]
$conSet :: [Hook SDLWindow]
onSet :: [Hook SDLWindow]
$conRemove :: [Hook SDLWindow]
onRemove :: [Hook SDLWindow]
$conAddRel :: [HookRel SDLWindow]
onAddRel :: [HookRel SDLWindow]
$conSetRel :: [HookRel SDLWindow]
onSetRel :: [HookRel SDLWindow]
$conRemoveRel :: [HookRel SDLWindow]
onRemoveRel :: [HookRel SDLWindow]
Component)

-- deriving newtype (Show)

initSdl :: IO ()
initSdl :: IO ()
initSdl = do
  version <- IO Int32
SDL3.getVersion
  let (major, rest) = fromIntegral version `divMod` (1000000 :: Int)
      (minor, micro) = rest `divMod` 1000
  putStrLn
    ( "sdl3-raw: linked against SDL "
        <> show major
        <> "."
        <> show minor
        <> "."
        <> show micro
    )

  -- The curated layer types the macro constant at the SDL_InitFlags
  -- newtype (the raw sDL_INIT_VIDEO CUInt stays available under
  -- SDL3.Sys.Bindgen.Init).
  ok <- SDL3.init SDL3.SDL_INIT_VIDEO
  unless ok (die "SDL_Init")

-- window <- withCString "sdl3-raw" $ \title -> SDL3.createWindow (ConstPtr title) 640 360 0

-- when (window == nullPtr) (die "Couldn't create window")

-- pure window

data SDLMessage e = SDLMessage {forall e. SDLMessage e -> SDL_EventType
eventType :: SDL3.SDL_EventType, forall e. SDLMessage e -> e
event :: e}
  deriving anyclass (Typeable (SDLMessage e)
Typeable (SDLMessage e) => Message (SDLMessage e)
forall e. Typeable e => Typeable (SDLMessage e)
forall {k} (m :: k). Typeable m => Message m
Message)
  deriving stock (Int -> SDLMessage e -> String -> String
[SDLMessage e] -> String -> String
SDLMessage e -> String
(Int -> SDLMessage e -> String -> String)
-> (SDLMessage e -> String)
-> ([SDLMessage e] -> String -> String)
-> Show (SDLMessage e)
forall e. Show e => Int -> SDLMessage e -> String -> String
forall e. Show e => [SDLMessage e] -> String -> String
forall e. Show e => SDLMessage e -> String
forall a.
(Int -> a -> String -> String)
-> (a -> String) -> ([a] -> String -> String) -> Show a
$cshowsPrec :: forall e. Show e => Int -> SDLMessage e -> String -> String
showsPrec :: Int -> SDLMessage e -> String -> String
$cshow :: forall e. Show e => SDLMessage e -> String
show :: SDLMessage e -> String
$cshowList :: forall e. Show e => [SDLMessage e] -> String -> String
showList :: [SDLMessage e] -> String -> String
Show)

data SDLEventsPlugin

instance Plugin SDLEventsPlugin where
  init :: System ()
init = do
    IO () -> System ()
forall a. IO a -> System a
forall (m :: * -> *) a. MonadIO m => IO a -> m a
liftIO IO ()
initSdl

    System () -> SystemConfig
forall a. ToSystems a => a -> SystemConfig
systems System ()
handleEvents
      SystemConfig -> (SystemConfig -> System ()) -> System ()
forall a b. a -> (a -> b) -> b
& forall sc. Schedule sc => SystemConfig -> System ()
forall {k} (sc :: k). Schedule sc => SystemConfig -> System ()
schedule @First

    (System (), System ()) -> SystemConfig
forall a. ToSystems a => a -> SystemConfig
systems (System ()
handleQuit, System ()
handleWindowClose)
      SystemConfig -> (SystemConfig -> SystemConfig) -> SystemConfig
forall a b. a -> (a -> b) -> b
& System () -> SystemConfig -> SystemConfig
forall a. ToSystems a => a -> SystemConfig -> SystemConfig
after System ()
handleEvents
      SystemConfig -> (SystemConfig -> System ()) -> System ()
forall a b. a -> (a -> b) -> b
& forall sc. Schedule sc => SystemConfig -> System ()
forall {k} (sc :: k). Schedule sc => SystemConfig -> System ()
schedule @First

-- addMessage @(SDLMessage SDL3.SDL_DisplayEvent)
-- addMessage @(SDLMessage SDl3.SDL_WindowEvent)
-- addMessage @(SDLMessage SDL3.SDL_KeyboardEvent)
-- addMessage @(SDLMessage SDLMouseButtonEvent)
-- addMessage @(SDLMessage SDLMouseMotionEvent)
-- addMessage @(SDLMessage SDLQuitEvent)

-- addSystems First handleEvents
-- addSystems First $ handleQuit `after` handleEvents

handleEvents :: System ()
handleEvents :: System ()
handleEvents = forall a b. Storable a => (Ptr a -> System b) -> System b
F.alloca @SDL3.SDL_Event ((Ptr SDL_Event -> System ()) -> System ())
-> (Ptr SDL_Event -> System ()) -> System ()
forall a b. (a -> b) -> a -> b
$ \Ptr SDL_Event
event -> do
  pending <- IO Bool -> System Bool
forall a. IO a -> System a
forall (m :: * -> *) a. MonadIO m => IO a -> m a
liftIO (IO Bool -> System Bool) -> IO Bool -> System Bool
forall a b. (a -> b) -> a -> b
$ Ptr SDL_Event -> IO Bool
SDL3.pollEvent Ptr SDL_Event
event
  when pending $ do
    e <- liftIO $ peek event
    eventType <- liftIO $ peek (castPtr event :: Ptr SDL3.SDL_EventType)
    handleEvent eventType e
    handleEvents

-- alloca @SDL3.SDL_Event $ \event -> do
--   liftIO SDL3.pollEventSafe
--   case event of
--     Nothing -> do
--       return ()
--     Just event -> do
--       handleEvent event
--       handleEvents

-- these correspond to https://wiki.libsdl.org/SDL3/SDL_Event
handleEvent :: SDL3.SDL_EventType -> SDL3.SDL_Event -> System ()
handleEvent :: SDL_EventType -> SDL_Event -> System ()
handleEvent SDL_EventType
t SDL_Event
e = case SDL_EventType
t of
  -- audio
  SDL_EventType
SDL3.SDL_EVENT_AUDIO_DEVICE_ADDED -> SDL_EventType -> SDL_AudioDeviceEvent -> System ()
forall {e}. Typeable e => SDL_EventType -> e -> System ()
s SDL_EventType
t SDL_Event
e.adevice
  SDL_EventType
SDL3.SDL_EVENT_AUDIO_DEVICE_FORMAT_CHANGED -> SDL_EventType -> SDL_AudioDeviceEvent -> System ()
forall {e}. Typeable e => SDL_EventType -> e -> System ()
s SDL_EventType
t SDL_Event
e.adevice
  SDL_EventType
SDL3.SDL_EVENT_AUDIO_DEVICE_REMOVED -> SDL_EventType -> SDL_AudioDeviceEvent -> System ()
forall {e}. Typeable e => SDL_EventType -> e -> System ()
s SDL_EventType
t SDL_Event
e.adevice
  -- TODO: camera
  -- TODO: clipboard
  -- display
  SDL_EventType
SDL3.SDL_EVENT_DISPLAY_ADDED -> SDL_EventType -> SDL_DisplayEvent -> System ()
forall {e}. Typeable e => SDL_EventType -> e -> System ()
s SDL_EventType
t SDL_Event
e.display
  SDL_EventType
SDL3.SDL_EVENT_DISPLAY_CONTENT_SCALE_CHANGED -> SDL_EventType -> SDL_DisplayEvent -> System ()
forall {e}. Typeable e => SDL_EventType -> e -> System ()
s SDL_EventType
t SDL_Event
e.display
  SDL_EventType
SDL3.SDL_EVENT_DISPLAY_CURRENT_MODE_CHANGED -> SDL_EventType -> SDL_DisplayEvent -> System ()
forall {e}. Typeable e => SDL_EventType -> e -> System ()
s SDL_EventType
t SDL_Event
e.display
  SDL_EventType
SDL3.SDL_EVENT_DISPLAY_DESKTOP_MODE_CHANGED -> SDL_EventType -> SDL_DisplayEvent -> System ()
forall {e}. Typeable e => SDL_EventType -> e -> System ()
s SDL_EventType
t SDL_Event
e.display
  SDL_EventType
SDL3.SDL_EVENT_DISPLAY_FIRST -> SDL_EventType -> SDL_DisplayEvent -> System ()
forall {e}. Typeable e => SDL_EventType -> e -> System ()
s SDL_EventType
t SDL_Event
e.display
  SDL_EventType
SDL3.SDL_EVENT_DISPLAY_LAST -> SDL_EventType -> SDL_DisplayEvent -> System ()
forall {e}. Typeable e => SDL_EventType -> e -> System ()
s SDL_EventType
t SDL_Event
e.display
  SDL_EventType
SDL3.SDL_EVENT_DISPLAY_MOVED -> SDL_EventType -> SDL_DisplayEvent -> System ()
forall {e}. Typeable e => SDL_EventType -> e -> System ()
s SDL_EventType
t SDL_Event
e.display
  SDL_EventType
SDL3.SDL_EVENT_DISPLAY_ORIENTATION -> SDL_EventType -> SDL_DisplayEvent -> System ()
forall {e}. Typeable e => SDL_EventType -> e -> System ()
s SDL_EventType
t SDL_Event
e.display
  SDL_EventType
SDL3.SDL_EVENT_DISPLAY_REMOVED -> SDL_EventType -> SDL_DisplayEvent -> System ()
forall {e}. Typeable e => SDL_EventType -> e -> System ()
s SDL_EventType
t SDL_Event
e.display
  SDL_EventType
SDL3.SDL_EVENT_DISPLAY_USABLE_BOUNDS_CHANGED -> SDL_EventType -> SDL_DisplayEvent -> System ()
forall {e}. Typeable e => SDL_EventType -> e -> System ()
s SDL_EventType
t SDL_Event
e.display
  -- TODO: gamepad
  -- TODO: gamepad axis
  -- TODO: gamepad button
  -- TODO: gamepad touchpad
  -- TODO: gamepad sensor
  -- TODO: drop
  -- TODO: finger
  -- TODO: pinch
  -- keyboard
  SDL_EventType
SDL3.SDL_EVENT_KEYBOARD_ADDED -> SDL_EventType -> SDL_KeyboardDeviceEvent -> System ()
forall {e}. Typeable e => SDL_EventType -> e -> System ()
s SDL_EventType
t SDL_Event
e.kdevice
  SDL_EventType
SDL3.SDL_EVENT_KEYBOARD_REMOVED -> SDL_EventType -> SDL_KeyboardDeviceEvent -> System ()
forall {e}. Typeable e => SDL_EventType -> e -> System ()
s SDL_EventType
t SDL_Event
e.kdevice
  -- key
  SDL_EventType
SDL3.SDL_EVENT_KEY_DOWN -> SDL_EventType -> SDL_KeyboardEvent -> System ()
forall {e}. Typeable e => SDL_EventType -> e -> System ()
s SDL_EventType
t SDL_Event
e.key
  SDL_EventType
SDL3.SDL_EVENT_KEY_UP -> SDL_EventType -> SDL_KeyboardEvent -> System ()
forall {e}. Typeable e => SDL_EventType -> e -> System ()
s SDL_EventType
t SDL_Event
e.key
  -- TODO: joystick
  -- TODO: joystick axis
  -- TODO: joystick ball
  -- TODO: joystick hat
  -- TODO: joystick battery
  -- TODO: joystick button
  -- mouse
  SDL_EventType
SDL3.SDL_EVENT_MOUSE_ADDED -> SDL_EventType -> SDL_MouseDeviceEvent -> System ()
forall {e}. Typeable e => SDL_EventType -> e -> System ()
s SDL_EventType
t SDL_Event
e.mdevice
  SDL_EventType
SDL3.SDL_EVENT_MOUSE_REMOVED -> SDL_EventType -> SDL_MouseDeviceEvent -> System ()
forall {e}. Typeable e => SDL_EventType -> e -> System ()
s SDL_EventType
t SDL_Event
e.mdevice
  -- mouse motion
  SDL_EventType
SDL3.SDL_EVENT_MOUSE_MOTION -> SDL_EventType -> SDL_MouseMotionEvent -> System ()
forall {e}. Typeable e => SDL_EventType -> e -> System ()
s SDL_EventType
t SDL_Event
e.motion
  -- mouse button
  SDL_EventType
SDL3.SDL_EVENT_MOUSE_BUTTON_DOWN -> SDL_EventType -> SDL_MouseButtonEvent -> System ()
forall {e}. Typeable e => SDL_EventType -> e -> System ()
s SDL_EventType
t SDL_Event
e.button
  SDL_EventType
SDL3.SDL_EVENT_MOUSE_BUTTON_UP -> SDL_EventType -> SDL_MouseButtonEvent -> System ()
forall {e}. Typeable e => SDL_EventType -> e -> System ()
s SDL_EventType
t SDL_Event
e.button
  -- mouse wheel
  SDL_EventType
SDL3.SDL_EVENT_MOUSE_WHEEL -> SDL_EventType -> SDL_MouseWheelEvent -> System ()
forall {e}. Typeable e => SDL_EventType -> e -> System ()
s SDL_EventType
t SDL_Event
e.wheel
  -- TODO: pen proximity
  -- TODO: pen touch
  -- TODO: pen motion
  -- TODO: pen button
  -- TODO: pen axis
  -- quit
  SDL_EventType
SDL3.SDL_EVENT_QUIT -> SDL_EventType -> SDL_QuitEvent -> System ()
forall {e}. Typeable e => SDL_EventType -> e -> System ()
s SDL_EventType
t SDL_Event
e.quit
  -- TODO: sensor
  -- TODO: edit
  -- TODO: edit candidates
  -- text
  SDL_EventType
SDL3.SDL_EVENT_TEXT_INPUT -> SDL_EventType -> SDL_TextInputEvent -> System ()
forall {e}. Typeable e => SDL_EventType -> e -> System ()
s SDL_EventType
t SDL_Event
e.text
  -- user
  SDL_EventType
SDL3.SDL_EVENT_USER -> SDL_EventType -> SDL_UserEvent -> System ()
forall {e}. Typeable e => SDL_EventType -> e -> System ()
s SDL_EventType
t SDL_Event
e.user
  -- window
  SDL_EventType
SDL3.SDL_EVENT_WINDOW_CLOSE_REQUESTED -> SDL_EventType -> SDL_WindowEvent -> System ()
forall {e}. Typeable e => SDL_EventType -> e -> System ()
s SDL_EventType
t SDL_Event
e.window
  SDL_EventType
SDL3.SDL_EVENT_WINDOW_DESTROYED -> SDL_EventType -> SDL_WindowEvent -> System ()
forall {e}. Typeable e => SDL_EventType -> e -> System ()
s SDL_EventType
t SDL_Event
e.window
  SDL_EventType
SDL3.SDL_EVENT_WINDOW_DISPLAY_CHANGED -> SDL_EventType -> SDL_WindowEvent -> System ()
forall {e}. Typeable e => SDL_EventType -> e -> System ()
s SDL_EventType
t SDL_Event
e.window
  SDL_EventType
SDL3.SDL_EVENT_WINDOW_DISPLAY_SCALE_CHANGED -> SDL_EventType -> SDL_WindowEvent -> System ()
forall {e}. Typeable e => SDL_EventType -> e -> System ()
s SDL_EventType
t SDL_Event
e.window
  SDL_EventType
SDL3.SDL_EVENT_WINDOW_ENTER_FULLSCREEN -> SDL_EventType -> SDL_WindowEvent -> System ()
forall {e}. Typeable e => SDL_EventType -> e -> System ()
s SDL_EventType
t SDL_Event
e.window
  SDL_EventType
SDL3.SDL_EVENT_WINDOW_EXPOSED -> SDL_EventType -> SDL_WindowEvent -> System ()
forall {e}. Typeable e => SDL_EventType -> e -> System ()
s SDL_EventType
t SDL_Event
e.window
  SDL_EventType
SDL3.SDL_EVENT_WINDOW_FIRST -> SDL_EventType -> SDL_WindowEvent -> System ()
forall {e}. Typeable e => SDL_EventType -> e -> System ()
s SDL_EventType
t SDL_Event
e.window
  SDL_EventType
SDL3.SDL_EVENT_WINDOW_FOCUS_GAINED -> SDL_EventType -> SDL_WindowEvent -> System ()
forall {e}. Typeable e => SDL_EventType -> e -> System ()
s SDL_EventType
t SDL_Event
e.window
  SDL_EventType
SDL3.SDL_EVENT_WINDOW_FOCUS_LOST -> SDL_EventType -> SDL_WindowEvent -> System ()
forall {e}. Typeable e => SDL_EventType -> e -> System ()
s SDL_EventType
t SDL_Event
e.window
  SDL_EventType
SDL3.SDL_EVENT_WINDOW_HDR_STATE_CHANGED -> SDL_EventType -> SDL_WindowEvent -> System ()
forall {e}. Typeable e => SDL_EventType -> e -> System ()
s SDL_EventType
t SDL_Event
e.window
  SDL_EventType
SDL3.SDL_EVENT_WINDOW_HIDDEN -> SDL_EventType -> SDL_WindowEvent -> System ()
forall {e}. Typeable e => SDL_EventType -> e -> System ()
s SDL_EventType
t SDL_Event
e.window
  SDL_EventType
SDL3.SDL_EVENT_WINDOW_HIT_TEST -> SDL_EventType -> SDL_WindowEvent -> System ()
forall {e}. Typeable e => SDL_EventType -> e -> System ()
s SDL_EventType
t SDL_Event
e.window
  SDL_EventType
SDL3.SDL_EVENT_WINDOW_ICCPROF_CHANGED -> SDL_EventType -> SDL_WindowEvent -> System ()
forall {e}. Typeable e => SDL_EventType -> e -> System ()
s SDL_EventType
t SDL_Event
e.window
  SDL_EventType
SDL3.SDL_EVENT_WINDOW_LAST -> SDL_EventType -> SDL_WindowEvent -> System ()
forall {e}. Typeable e => SDL_EventType -> e -> System ()
s SDL_EventType
t SDL_Event
e.window
  SDL_EventType
SDL3.SDL_EVENT_WINDOW_LEAVE_FULLSCREEN -> SDL_EventType -> SDL_WindowEvent -> System ()
forall {e}. Typeable e => SDL_EventType -> e -> System ()
s SDL_EventType
t SDL_Event
e.window
  SDL_EventType
SDL3.SDL_EVENT_WINDOW_MAXIMIZED -> SDL_EventType -> SDL_WindowEvent -> System ()
forall {e}. Typeable e => SDL_EventType -> e -> System ()
s SDL_EventType
t SDL_Event
e.window
  SDL_EventType
SDL3.SDL_EVENT_WINDOW_METAL_VIEW_RESIZED -> SDL_EventType -> SDL_WindowEvent -> System ()
forall {e}. Typeable e => SDL_EventType -> e -> System ()
s SDL_EventType
t SDL_Event
e.window
  SDL_EventType
SDL3.SDL_EVENT_WINDOW_MINIMIZED -> SDL_EventType -> SDL_WindowEvent -> System ()
forall {e}. Typeable e => SDL_EventType -> e -> System ()
s SDL_EventType
t SDL_Event
e.window
  SDL_EventType
SDL3.SDL_EVENT_WINDOW_MOUSE_ENTER -> SDL_EventType -> SDL_WindowEvent -> System ()
forall {e}. Typeable e => SDL_EventType -> e -> System ()
s SDL_EventType
t SDL_Event
e.window
  SDL_EventType
SDL3.SDL_EVENT_WINDOW_MOUSE_LEAVE -> SDL_EventType -> SDL_WindowEvent -> System ()
forall {e}. Typeable e => SDL_EventType -> e -> System ()
s SDL_EventType
t SDL_Event
e.window
  SDL_EventType
SDL3.SDL_EVENT_WINDOW_MOVED -> SDL_EventType -> SDL_WindowEvent -> System ()
forall {e}. Typeable e => SDL_EventType -> e -> System ()
s SDL_EventType
t SDL_Event
e.window
  SDL_EventType
SDL3.SDL_EVENT_WINDOW_OCCLUDED -> SDL_EventType -> SDL_WindowEvent -> System ()
forall {e}. Typeable e => SDL_EventType -> e -> System ()
s SDL_EventType
t SDL_Event
e.window
  SDL_EventType
SDL3.SDL_EVENT_WINDOW_PIXEL_SIZE_CHANGED -> SDL_EventType -> SDL_WindowEvent -> System ()
forall {e}. Typeable e => SDL_EventType -> e -> System ()
s SDL_EventType
t SDL_Event
e.window
  SDL_EventType
SDL3.SDL_EVENT_WINDOW_RESIZED -> SDL_EventType -> SDL_WindowEvent -> System ()
forall {e}. Typeable e => SDL_EventType -> e -> System ()
s SDL_EventType
t SDL_Event
e.window
  SDL_EventType
SDL3.SDL_EVENT_WINDOW_RESTORED -> SDL_EventType -> SDL_WindowEvent -> System ()
forall {e}. Typeable e => SDL_EventType -> e -> System ()
s SDL_EventType
t SDL_Event
e.window
  SDL_EventType
SDL3.SDL_EVENT_WINDOW_SAFE_AREA_CHANGED -> SDL_EventType -> SDL_WindowEvent -> System ()
forall {e}. Typeable e => SDL_EventType -> e -> System ()
s SDL_EventType
t SDL_Event
e.window
  SDL_EventType
SDL3.SDL_EVENT_WINDOW_SHOWN -> SDL_EventType -> SDL_WindowEvent -> System ()
forall {e}. Typeable e => SDL_EventType -> e -> System ()
s SDL_EventType
t SDL_Event
e.window
  -- common
  SDL_EventType
t -> SDL_EventType -> SDL_CommonEvent -> System ()
forall {e}. Typeable e => SDL_EventType -> e -> System ()
s SDL_EventType
t SDL_Event
e.common
  where
    s :: SDL_EventType -> e -> System ()
s SDL_EventType
t e
a = SDLMessage e -> System ()
forall m. Message m => m -> System ()
Messages.write (SDLMessage e -> System ()) -> SDLMessage e -> System ()
forall a b. (a -> b) -> a -> b
$ SDL_EventType -> e -> SDLMessage e
forall e. SDL_EventType -> e -> SDLMessage e
SDLMessage SDL_EventType
t e
a

handleQuit :: System ()
handleQuit :: System ()
handleQuit = do
  messages <- forall m. Message m => System [m]
Messages.read @(SDLMessage SDL3.SDL_QuitEvent)
  unless (null messages) $ liftIO exitSuccess

handleWindowClose :: System ()
handleWindowClose :: System ()
handleWindowClose = do
  messages <- (SDLMessage SDL_WindowEvent -> Bool)
-> [SDLMessage SDL_WindowEvent] -> [SDLMessage SDL_WindowEvent]
forall a. (a -> Bool) -> [a] -> [a]
filter (\(SDLMessage SDL_EventType
t SDL_WindowEvent
_) -> SDL_EventType
t SDL_EventType -> SDL_EventType -> Bool
forall a. Eq a => a -> a -> Bool
== SDL_EventType
SDL3.SDL_EVENT_WINDOW_CLOSE_REQUESTED) ([SDLMessage SDL_WindowEvent] -> [SDLMessage SDL_WindowEvent])
-> System [SDLMessage SDL_WindowEvent]
-> System [SDLMessage SDL_WindowEvent]
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> forall m. Message m => System [m]
Messages.read @(SDLMessage SDL3.SDL_WindowEvent)

  for_ messages $ \(SDLMessage SDL_EventType
_ SDL3.SDL_WindowEvent {SDL_WindowID
windowID :: SDL_WindowID
windowID :: SDL_WindowEvent -> SDL_WindowID
windowID}) -> do
    window <- IO (Ptr SDL_Window) -> System (Ptr SDL_Window)
forall a. IO a -> System a
forall (m :: * -> *) a. MonadIO m => IO a -> m a
liftIO (IO (Ptr SDL_Window) -> System (Ptr SDL_Window))
-> IO (Ptr SDL_Window) -> System (Ptr SDL_Window)
forall a b. (a -> b) -> a -> b
$ SDL_WindowID -> IO (Ptr SDL_Window)
SDL3.getWindowFromID SDL_WindowID
windowID
    unless (window == nullPtr) $ do
      liftIO $ destroyWindow window

      a <-
        [q|(Entity, SDLWindow) / With SDLWindow|]
          & qfilter (\(Entity
_, SDLWindow Ptr SDL_Window
p) -> Ptr SDL_Window
p Ptr SDL_Window -> Ptr SDL_Window -> Bool
forall a. Eq a => a -> a -> Bool
== Ptr SDL_Window
window)
          & qmap fst
          & single

      traverse_ despawn a

-- $intro
-- This package provides the 'sdlPlugin' for @Mischief@, along with a few components.
--
-- These are necessary to run any SDL-based packages, such as @MischiefInput@, and @MischiefRender@.
--
-- In order to properly run this, you'll need to build / install SDL locally. This can be done via:
--
-- @
-- git clone --recurse-submodules https://github.com/PVDoriginal/mischief.git
-- cd mischief\/external\/SDL3
-- mkdir -p build && cd build
-- cmake -DCMAKE_BUILD_TYPE=Release -GNinja ..
-- cmake --build . --config Release --parallel
-- sudo cmake --install . --config Release   # omit sudo on Windows
-- @
--
-- On @Windows@, ensure @SDL3.dll@ is available in @PATH@ (or next to your .exe). If @pkg-config@ cannot find SDL3, set:
--
-- @
-- set PKG_CONFIG_PATH=path\to\SDL3\lib\pkgconfig
-- # or
-- \$env:PKG_CONFIG_PATH="path\to\SDL3\lib\pkgconfig"
-- @