packages feed

glfw-group (empty) → 0.1.0.0

raw patch · 15 files changed

+376/−0 lines, 15 filesdep +GLFW-bdep +basedep +containerssetup-changed

Dependencies added: GLFW-b, base, containers, glfw-group, stm, text

Files

+ CHANGELOG.md view
@@ -0,0 +1,11 @@+# Changelog for `glfw-group`++All notable changes to this project will be documented in this file.++The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),+and this project adheres to the+[Haskell Package Versioning Policy](https://pvp.haskell.org/).++## Unreleased++## 0.1.0.0 - YYYY-MM-DD
+ LICENSE view
@@ -0,0 +1,26 @@+Copyright 2025 Yoshikuni Jujo++Redistribution and use in source and binary forms, with or without+modification, are permitted provided that the following conditions are met:++1.  Redistributions of source code must retain the above copyright notice, this+    list of conditions and the following disclaimer.++2.  Redistributions in binary form must reproduce the above copyright notice,+    this list of conditions and the following disclaimer in the documentation+    and/or other materials provided with the distribution.++3.  Neither the name of the copyright holder nor the names of its contributors+    may be used to endorse or promote products derived from this software+    without specific prior written permission.++THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR+ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON+ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ README.md view
@@ -0,0 +1,1 @@+# glfw-group
+ Setup.hs view
@@ -0,0 +1,2 @@+import Distribution.Simple+main = defaultMain
+ app/Main.hs view
@@ -0,0 +1,6 @@+module Main (main) where++import Lib++main :: IO ()+main = someFunc
+ glfw-group.cabal view
@@ -0,0 +1,88 @@+cabal-version: 2.2++-- This file has been generated from package.yaml by hpack version 0.37.0.+--+-- see: https://github.com/sol/hpack++name:           glfw-group+version:        0.1.0.0+synopsis:       GLFW package with window groups destroyed together+description:    Please see the README on GitHub at <https://github.com/YoshikuniJujo/glfw-group#readme>+category:       Graphics+homepage:       https://github.com/YoshikuniJujo/glfw-group#readme+bug-reports:    https://github.com/YoshikuniJujo/glfw-group/issues+author:         Yoshikuni Jujo+maintainer:     yoshikuni.jujo@gmail.com+copyright:      (c) 2025 Yoshikuni Jujo+license:        BSD-3-Clause+license-file:   LICENSE+build-type:     Simple+extra-doc-files:+    README.md+    CHANGELOG.md++source-repository head+  type: git+  location: https://github.com/YoshikuniJujo/glfw-group++library+  exposed-modules:+      Graphics.UI.GlfwG+      Graphics.UI.GlfwG.Gamepad+      Graphics.UI.GlfwG.Joystick+      Graphics.UI.GlfwG.Key+      Graphics.UI.GlfwG.Mouse+      Graphics.UI.GlfwG.Window+      Graphics.UI.GlfwG.Window.Type+      Lib+  other-modules:+      Paths_glfw_group+  autogen-modules:+      Paths_glfw_group+  hs-source-dirs:+      src+  ghc-options: -Wall -Wcompat -Widentities -Wincomplete-record-updates -Wincomplete-uni-patterns -Wmissing-export-lists -Wmissing-home-modules -Wpartial-fields -Wredundant-constraints+  build-depends:+      GLFW-b <4+    , base >=4.7 && <5+    , containers <1+    , stm <3+    , text <3+  default-language: Haskell2010++executable glfw-group-exe+  main-is: Main.hs+  other-modules:+      Paths_glfw_group+  autogen-modules:+      Paths_glfw_group+  hs-source-dirs:+      app+  ghc-options: -Wall -Wcompat -Widentities -Wincomplete-record-updates -Wincomplete-uni-patterns -Wmissing-export-lists -Wmissing-home-modules -Wpartial-fields -Wredundant-constraints -threaded -rtsopts -with-rtsopts=-N+  build-depends:+      GLFW-b <4+    , base >=4.7 && <5+    , containers <1+    , glfw-group+    , stm <3+    , text <3+  default-language: Haskell2010++test-suite glfw-group-test+  type: exitcode-stdio-1.0+  main-is: Spec.hs+  other-modules:+      Paths_glfw_group+  autogen-modules:+      Paths_glfw_group+  hs-source-dirs:+      test+  ghc-options: -Wall -Wcompat -Widentities -Wincomplete-record-updates -Wincomplete-uni-patterns -Wmissing-export-lists -Wmissing-home-modules -Wpartial-fields -Wredundant-constraints -threaded -rtsopts -with-rtsopts=-N+  build-depends:+      GLFW-b <4+    , base >=4.7 && <5+    , containers <1+    , glfw-group+    , stm <3+    , text <3+  default-language: Haskell2010
+ src/Graphics/UI/GlfwG.hs view
@@ -0,0 +1,50 @@+{-# LANGUAGE ImportQualifiedPost #-}+{-# LANGUAGE TupleSections #-}+{-# LANGUAGE RankNTypes #-}+{-# LANGUAGE MonoLocalBinds #-}+{-# LANGUAGE ViewPatterns #-}+{-# OPTIONS_GHC -Wall -fno-warn-tabs #-}++module Graphics.UI.GlfwG (++	init, ErrorMessage, getRequiredInstanceExtensions,++	GlfwB.pollEvents, GlfwB.waitEvents++	) where++import Prelude hiding (init)++import Foreign.Ptr+import Foreign.Storable+import Foreign.C.String+import Control.Exception+import Data.Bool+import Data.Text qualified as Txt+import Data.Text.Foreign qualified as Txt++import qualified Graphics.UI.GLFW as GlfwB++init :: (ErrorMessage -> IO a) -> IO a -> IO a+init hdl cmp = GlfwB.init >>= bool+	(hdl $ "Gpu.Vulkan.Khr.Surface.Glfw: " +++		"GLFW-b.Graphics.UI.GLFW.init return False")+	(finally cmp GlfwB.terminate)++type ErrorMessage = String++getRequiredInstanceExtensions :: IO [Txt.Text]+getRequiredInstanceExtensions = (cstrToText `mapM`) =<< GlfwB.getRequiredInstanceExtensions++cstrToText :: CString -> IO Txt.Text+cstrToText cs = Txt.peekCStringLen =<< cstringToCStringLen cs++cstringLength :: CString -> IO Int+cstringLength pc = do+	c <- peek pc+	case c of+		0 -> pure 0+		_ -> (+ 1) <$> cstringLength (pc `plusPtr` 1)++cstringToCStringLen :: CString -> IO CStringLen+cstringToCStringLen cs = (cs ,) <$> cstringLength cs
+ src/Graphics/UI/GlfwG/Gamepad.hs view
@@ -0,0 +1,9 @@+{-# OPTIONS_GHC -Wall -fno-warn-tabs #-}++module Graphics.UI.GlfwG.Gamepad (+	GamepadButton(..), GamepadAxis(..), GamepadButtonState(..),+	GamepadState(..), joystickIsGamepad, getGamepadName, getGamepadState,+	updateGamepadMappings+	) where++import Graphics.UI.GLFW
+ src/Graphics/UI/GlfwG/Joystick.hs view
@@ -0,0 +1,10 @@+{-# OPTIONS_GHC -Wall -fno-warn-tabs #-}++module Graphics.UI.GlfwG.Joystick (+	Joystick(..), JoystickState(..), JoystickButtonState(..),+	joystickPresent, joystickIsGamepad, getJoystickAxes, getJoystickButtons,+	getJoystickHats, JoystickHatState(..), getJoystickName, getJoystickGUID,+	setJoystickCallback, JoystickCallback+	) where++import Graphics.UI.GLFW
+ src/Graphics/UI/GlfwG/Key.hs view
@@ -0,0 +1,7 @@+{-# LANGUAGE ImportQualifiedPost #-}+{-# OPTIONS_GHC -Wall -fno-warn-tabs #-}++module Graphics.UI.GlfwG.Key (+	B.Key(..), B.KeyState(..), B.ModifierKeys(..) ) where++import Graphics.UI.GLFW qualified as B
+ src/Graphics/UI/GlfwG/Mouse.hs view
@@ -0,0 +1,18 @@+{-# LANGUAGE ImportQualifiedPost #-}+{-# OPTIONS_GHC -Wall -fno-warn-tabs #-}++module Graphics.UI.GlfwG.Mouse (++	getButton, B.MouseButton(..), B.MouseButtonState(..),+	getCursorPos++	) where++import Graphics.UI.GLFW qualified as B+import Graphics.UI.GlfwG.Window.Type qualified as Win++getButton :: Win.W sw -> B.MouseButton -> IO B.MouseButtonState+getButton (Win.W w) = B.getMouseButton w++getCursorPos :: Win.W sw -> IO (Double, Double)+getCursorPos (Win.W w) = B.getCursorPos w
+ src/Graphics/UI/GlfwG/Window.hs view
@@ -0,0 +1,132 @@+{-# LANGUAGE ImportQualifiedPost #-}+{-# LANGUAGE BlockArguments, LambdaCase #-}+{-# LANGUAGE RankNTypes #-}+{-# LANGUAGE ViewPatterns #-}+{-# OPTIONS_GHC -Wall -fno-warn-tabs #-}++module Graphics.UI.GlfwG.Window (++	-- * CREATE AND DESTROY++	W, create, Group, group, create', unsafeDestroy, lookup,++	shouldClose, setShouldClose,++	-- ** HINT++	hint, B.WindowHint(..),+	B.ClientAPI(..),++	-- * PARAMETER++	getSize, setSize,+	getFrameSize,+	getFramebufferSize,++	-- * CALLBACK++	setKeyCallback, KeyCallback,+	setFramebufferSizeCallback, B.FramebufferSizeCallback,++	-- * STATE++	getKey++	) where++import Prelude hiding (lookup)++import Control.Concurrent.STM+import Control.Concurrent.STM.TSem+import Data.Map qualified as M++import Graphics.UI.GLFW qualified as B+import Graphics.UI.GlfwG.Window.Type++data Group s k = Group TSem (TVar (M.Map k (W s)))++create :: Int -> Int -> String -> Maybe B.Monitor -> Maybe B.Window ->+	(forall s . W s -> IO a) -> IO a+create wd hg ttl mm mws f = group \g -> f . fromRight =<< create' g () wd hg ttl mm mws+	where fromRight = \case Left _ -> error "never occur"; Right w -> w++group :: (forall s . Group s k -> IO a) -> IO a+group f = do+	(sem, m) <- atomically $ (,) <$> newTSem 1 <*> newTVar M.empty+	rtn <- f $ Group sem m+	((\(W w) -> B.destroyWindow w) `mapM_`) =<< atomically (readTVar m)+	pure rtn++create' :: Ord k => Group s k -> k -> Int -> Int -> String ->+	Maybe B.Monitor -> Maybe B.Window -> IO (Either String (W s))+create' (Group sem ws) k wd hg ttl mm mws = do+	ok <- atomically do+		mx <- M.lookup k <$> readTVar ws+		case mx of+			Nothing -> waitTSem sem >> pure True+			Just _ -> pure False+	if ok+	then do	mw <- (W <$>) <$> B.createWindow wd hg ttl mm mws+		case mw of+			Just w -> atomically do+				modifyTVar ws (M.insert k w) +				signalTSem sem+				pure $ Right w+			Nothing -> pure . Left $+				"Gpu.Vulkan.Khr.Surface." +++				"Glfw.Window.create': GLFW-b: error"+	else pure . Left $ "Gpu.Vulkan.Khr.Surface.Glfw.Window.create': " +++		"The key already exist"++unsafeDestroy :: Ord k => Group s k -> k -> IO (Either String ())+unsafeDestroy (Group sem ws) k = do+	mw <- atomically do+		mx <- M.lookup k <$> readTVar ws+		case mx of+			Nothing -> pure Nothing+			Just _ -> waitTSem sem >> pure mx+	case mw of+		Nothing -> pure . Left $+			"Gpu.Vulkan.Khr.Surface.Glfw.Window.destroy: " +++			"No such key"+		Just (W w) -> do+			B.destroyWindow w+			atomically do+				modifyTVar ws (M.delete k)+				signalTSem sem+				pure $ Right ()++hint :: B.WindowHint -> IO ()+hint = B.windowHint++lookup :: Ord k => Group s k -> k -> IO (Maybe (W s))+lookup (Group _sem ws) k = atomically $ M.lookup k <$> readTVar ws++setFramebufferSizeCallback :: W s -> Maybe B.FramebufferSizeCallback -> IO ()+setFramebufferSizeCallback (W w) = B.setFramebufferSizeCallback w++getSize :: W sw -> IO (Int, Int)+getSize (W w) = B.getWindowSize w++setSize :: W sw -> Int -> Int -> IO ()+setSize (W w) = B.setWindowSize w++getFrameSize :: W sw -> IO (Int, Int, Int, Int)+getFrameSize (W w) = B.getWindowFrameSize w++getFramebufferSize :: W sw -> IO (Int, Int)+getFramebufferSize (W w) = B.getFramebufferSize w++setKeyCallback :: W s -> Maybe (KeyCallback s) -> IO ()+setKeyCallback (W w) = B.setKeyCallback w . ((. W) <$>)++type KeyCallback s = W s -> B.Key -> Int -> B.KeyState -> B.ModifierKeys -> IO ()++shouldClose :: W sw -> IO Bool+shouldClose (W w) = B.windowShouldClose w++setShouldClose :: W sw -> Bool -> IO ()+setShouldClose (W w) = B.setWindowShouldClose w++getKey :: W sw -> B.Key -> IO B.KeyState+getKey (W w) = B.getKey w
+ src/Graphics/UI/GlfwG/Window/Type.hs view
@@ -0,0 +1,8 @@+{-# LANGUAGE ImportQualifiedPost #-}+{-# OPTIONS_GHC -Wall -fno-warn-tabs #-}++module Graphics.UI.GlfwG.Window.Type where++import Graphics.UI.GLFW qualified as B++newtype W s = W B.Window deriving (Eq, Ord, Show)
+ src/Lib.hs view
@@ -0,0 +1,6 @@+module Lib+    ( someFunc+    ) where++someFunc :: IO ()+someFunc = putStrLn "someFunc"
+ test/Spec.hs view
@@ -0,0 +1,2 @@+main :: IO ()+main = putStrLn "Test suite not yet implemented"