From 899979e2b5e0c74dc236e89c9460d491e0e531c6 Mon Sep 17 00:00:00 2001
From: Jens Nolte <git@queezle.net>
Date: Tue, 26 Jul 2022 01:42:27 +0200
Subject: [PATCH] Update example to render layer shell surface

---
 example/Main.hs      | 137 ++++++++++++++++++++++++++++++++++++++++++-
 quasar-wayland.cabal |   3 +
 2 files changed, 138 insertions(+), 2 deletions(-)

diff --git a/example/Main.hs b/example/Main.hs
index 36bc935..544c887 100644
--- a/example/Main.hs
+++ b/example/Main.hs
@@ -1,16 +1,149 @@
 module Main (main) where
 
+import Data.List (intersperse)
+import Data.Foldable (toList)
 import Quasar
 import Quasar.Prelude
 import Quasar.Timer
 import Quasar.Wayland.Client
+import Quasar.Wayland.Client.Buffer
+import Quasar.Wayland.Client.JuicyPixels
+import Quasar.Wayland.Protocol
+import Quasar.Wayland.Protocol.Generated
+
+import Codec.Picture
+
+
+data Dimensions = Dimensions {
+  width :: Int,
+  height :: Int,
+  aspect :: Double
+}
+
+data Position = Position {
+  dimensions :: Dimensions,
+  pixelX :: Int,
+  pixelY :: Int,
+  u :: Double,
+  v :: Double,
+  x :: Double,
+  y :: Double
+}
+
+mkDimensions :: Int -> Int -> Dimensions
+mkDimensions width height = Dimensions { width, height, aspect }
+  where
+    aspect :: Double
+    aspect = (fromIntegral width) / (fromIntegral height)
+
+mkPosition :: Dimensions -> Int -> Int -> Position
+mkPosition dimensions pixelX pixelY = Position { dimensions, pixelX, pixelY, u, v, x, y }
+  where
+    width' = width dimensions
+    height' = height dimensions
+    u :: Double
+    u = (fromIntegral pixelX) / (fromIntegral width')
+    v :: Double
+    v = (fromIntegral pixelY) / (fromIntegral height')
+    innerRadius :: Int
+    innerRadius = div (min width' height') 2
+    x :: Double
+    x = (fromIntegral $ pixelX - (div width' 2)) / (fromIntegral innerRadius)
+    y :: Double
+    y = (fromIntegral $ pixelY - (div height' 2)) / (fromIntegral innerRadius)
+
+color :: RealFrac a => a -> a -> a -> PixelRGBA8
+color r g b = PixelRGBA8 (toWord r) (toWord g) (toWord b) 255
+  where
+    toWord = truncate . (* 255) . (max 0) . (min 1)
+
+gradient :: Position -> PixelRGBA8
+gradient p = color (u p) 0 (v p)
+
+solidColor :: Position -> PixelRGBA8
+solidColor p = color 255 0 0
+
+mkImage :: (Position -> PixelRGBA8) -> Image PixelRGBA8
+mkImage fn = generateImage pixel width height
+  where
+    width :: Int
+    width = 512
+    height :: Int
+    height = 512
+    dimensions :: Dimensions
+    dimensions = mkDimensions width height
+    pixel :: Int -> Int -> PixelRGBA8
+    pixel x y = fn $ mkPosition dimensions x y
+
 
 main :: IO ()
 main = do
-  runQuasarAndExit (stderrLogger LogLevelInfo) do
+  runQuasarAndExit (stderrLogger LogLevelWarning) do
     traceIO "Connecting"
     client <- connectWaylandClient
     traceIO "Connected"
-    await =<< newDelay 1000000
+
+    join $ liftIO $ atomically do
+
+      wlCompositor <- bindSingleton @Interface_wl_compositor client.registry
+
+      shm <- newShmBufferManager client
+
+      wlSurface <- wlCompositor.create_surface
+      setMessageHandler wlSurface EventHandler_wl_surface {
+        enter = \_ -> pure (),
+        leave = \_ -> pure ()
+      }
+
+      --xdgWmBase <- bindSingleton @Interface_xdg_wm_base client.registry
+      --setMessageHandler xdgWmBase EventHandler_xdg_wm_base {
+      --  ping = \serial -> xdgWmBase.pong serial
+      --}
+
+      --xdgSurface <- xdgWmBase.get_xdg_surface wlSurface
+      --setMessageHandler xdgSurface EventHandler_xdg_surface {
+      --  configure = \serial -> xdgSurface.ack_configure serial
+      --}
+      --xdgToplevel <- xdgSurface.get_toplevel
+      --setMessageHandler xdgToplevel EventHandler_xdg_toplevel {
+      --  configure = \_ _ _ -> pure (),
+      --  close = pure ()
+      --}
+
+      --xdgToplevel.set_title "foobar"
+
+
+      wlrLayerShell <- bindSingleton @Interface_zwlr_layer_shell_v1 client.registry
+
+      wlrLayerSurface <- wlrLayerShell.get_layer_surface wlSurface Nothing 2 "demo"
+      setMessageHandler wlrLayerSurface EventHandler_zwlr_layer_surface_v1 {
+        configure = \serial width height -> wlrLayerSurface.ack_configure serial,
+        closed = pure ()
+      }
+      wlrLayerSurface.set_size 512 512
+
+      wlSurface.commit
+      -- Should await first `configure` event
+
+      pure do
+        buffer <- liftIO $ toImageBuffer shm (mkImage gradient)
+
+        liftIO $ atomically do
+          wlSurface.attach (Just buffer) 0 0
+          wlSurface.commit
+
+        -- buffer2 <- liftIO $ toImageBuffer shm (wallpaperImage wallpaper)
+
+        --liftIO $ atomically do
+        --  wlSurface.attach (Nothing) 0 0
+        --  --wlSurface.damage 0 0 100 100
+        --  wlSurface.commit
+
+        traceIO . ("shm buffer formats: " <>) . mconcat . intersperse ", " . fmap show . toList =<< await shm.formats
+
+        pure ()
+
+    traceIO "Waiting 2s"
+    await =<< newDelay 2000000
     traceIO "Closing"
   traceIO "Closed"
diff --git a/quasar-wayland.cabal b/quasar-wayland.cabal
index 9947211..a504901 100644
--- a/quasar-wayland.cabal
+++ b/quasar-wayland.cabal
@@ -112,8 +112,11 @@ library
 executable quasar-wayland-example
   import: shared-executable-properties
   build-depends:
+    base,
+    JuicyPixels,
     quasar,
     quasar-wayland,
+    stm,
   main-is: Main.hs
   hs-source-dirs:
     example
-- 
GitLab