basic functionality on Wayland and X11

This commit is contained in:
mtgmonkey
2025-12-11 18:15:32 +01:00
parent ab69702910
commit 8a16c6695e
16 changed files with 14299 additions and 190 deletions

2
.gitignore vendored Normal file
View File

@@ -0,0 +1,2 @@
dist-newstyle
result

3
.gitmodules vendored
View File

@@ -1,3 +0,0 @@
[submodule "lib/RGFW"]
path = lib/RGFW
url = https://github.com/ColleagueRiley/RGFW

27
CHANGELOG.md Normal file
View File

@@ -0,0 +1,27 @@
# Changelog
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.1.0/),
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
## [Eventual]
### Added
- support for Windows
- support for actually doing anything
- autogen code
## 0.1.0.0 -- 2025-12-10
### Removed
- `main` function and its functionality
### Changed
- migrate to Cabal; Nix still works
- now a library
- build on Nix with `nix build`. object file is in `result/lib/hs-rgfw.so`
- build on other platforms with `cabal build` after installing dependencies.

29
LICENSE Normal file
View File

@@ -0,0 +1,29 @@
Copyright (c) 2025, andromeda
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
* 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.
* 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.

12
Setup.hs Normal file
View File

@@ -0,0 +1,12 @@
{-# LANGUAGE CPP #-}
module Main (main) where
import Distribution.Simple (defaultMain)
import System.Process (callCommand)
main :: IO ()
main = do
callCommand "./scripts/generate.sh"
defaultMain
callCommand "./scripts/delete-generated.sh"

6
flake.lock generated
View File

@@ -2,11 +2,11 @@
"nodes": {
"nixpkgs": {
"locked": {
"lastModified": 1764947035,
"narHash": "sha256-EYHSjVM4Ox4lvCXUMiKKs2vETUSL5mx+J2FfutM7T9w=",
"lastModified": 1765270179,
"narHash": "sha256-g2a4MhRKu4ymR4xwo+I+auTknXt/+j37Lnf0Mvfl1rE=",
"owner": "NixOS",
"repo": "nixpkgs",
"rev": "a672be65651c80d3f592a89b3945466584a22069",
"rev": "677fbe97984e7af3175b6c121f3c39ee5c8d62c9",
"type": "github"
},
"original": {

152
flake.nix
View File

@@ -1,97 +1,79 @@
{
inputs = {
nixpkgs.url = "nixpkgs/nixpkgs-unstable";
self.submodules = true;
};
outputs = {nixpkgs, ...}: let
outputs = {
nixpkgs,
self,
...
}: let
package = {
mkDerivation,
base,
gl,
lib,
libGL,
libX11,
libxkbcommon,
wayland,
xcursor,
xi,
xrandr,
}:
mkDerivation {
pname = "hs-rgfw";
version = "0.1.0.0";
src = ./.;
preBuild = ''
${lib.getExe pkgs.wayland-scanner} public-code ${pkgs.wayland-protocols}/share/wayland-protocols/stable/xdg-shell/xdg-shell.xml ./lib/xdg-shell.c
${lib.getExe pkgs.wayland-scanner} public-code ${pkgs.wayland-protocols}/share/wayland-protocols/staging/xdg-toplevel-icon/xdg-toplevel-icon-v1.xml ./lib/xdg-toplevel-icon-v1.c
${lib.getExe pkgs.wayland-scanner} public-code ${pkgs.wayland-protocols}/share/wayland-protocols/unstable/xdg-decoration/xdg-decoration-unstable-v1.xml ./lib/xdg-decoration-unstable-v1.c
${lib.getExe pkgs.wayland-scanner} public-code ${pkgs.wayland-protocols}/share/wayland-protocols/unstable/relative-pointer/relative-pointer-unstable-v1.xml ./lib/relative-pointer-unstable-v1.c
${lib.getExe pkgs.wayland-scanner} public-code ${pkgs.wayland-protocols}/share/wayland-protocols/unstable/pointer-constraints/pointer-constraints-unstable-v1.xml ./lib/pointer-constraints-unstable-v1.c
${lib.getExe pkgs.wayland-scanner} public-code ${pkgs.wayland-protocols}/share/wayland-protocols/unstable/xdg-output/xdg-output-unstable-v1.xml ./lib/xdg-output-unstable-v1.c
${lib.getExe pkgs.wayland-scanner} client-header ${pkgs.wayland-protocols}/share/wayland-protocols/stable/xdg-shell/xdg-shell.xml ./lib/xdg-shell.h
${lib.getExe pkgs.wayland-scanner} client-header ${pkgs.wayland-protocols}/share/wayland-protocols/staging/xdg-toplevel-icon/xdg-toplevel-icon-v1.xml ./lib/xdg-toplevel-icon-v1.h
${lib.getExe pkgs.wayland-scanner} client-header ${pkgs.wayland-protocols}/share/wayland-protocols/unstable/xdg-decoration/xdg-decoration-unstable-v1.xml ./lib/xdg-decoration-unstable-v1.h
${lib.getExe pkgs.wayland-scanner} client-header ${pkgs.wayland-protocols}/share/wayland-protocols/unstable/relative-pointer/relative-pointer-unstable-v1.xml ./lib/relative-pointer-unstable-v1.h
${lib.getExe pkgs.wayland-scanner} client-header ${pkgs.wayland-protocols}/share/wayland-protocols/unstable/pointer-constraints/pointer-constraints-unstable-v1.xml ./lib/pointer-constraints-unstable-v1.h
${lib.getExe pkgs.wayland-scanner} client-header ${pkgs.wayland-protocols}/share/wayland-protocols/unstable/xdg-output/xdg-output-unstable-v1.xml ./lib/xdg-output-unstable-v1.h
'';
libraryHaskellDepends = [
base
];
libraryPkgconfigDepends = [
gl
libGL
libX11
libxkbcommon
wayland
xcursor
xi
xrandr
];
postInstall = ''
'';
homepage = "https://git.mtgmonkey.net/Andromeda/hs-rgfw";
license = lib.licenses.bsd3;
platforms = ["x86_64-linux"];
};
system = "x86_64-linux";
pkgs = nixpkgs.legacyPackages.${system};
debugGhcOptions = pkgs.lib.concatStringsSep " " (debugGhcFlags ++ commonGhcFlags);
debugGhcFlags =
[
"-O0"
"-Wall"
"-Widentities"
"-Wincomplete-record-updates"
"-Wincomplete-uni-patterns"
# "-Wmissing-export-lists"
"-Wmissing-home-modules"
"-Wpartial-fields"
"-Wredundant-constraints"
]
++ commonGhcFlags;
haddockOptions = pkgs.lib.concatStringsSep " " haddockFlags;
haddockFlags = [
"--html"
"--odir docs"
"--optghc=-i./src"
"src/Game.hs"
];
releaseGhcOptions = pkgs.lib.concatStringsSep " " (releaseGhcFlags ++ commonGhcFlags);
releaseGhcFlags =
[
"-O2"
"-threaded"
"-rtsopts"
"-with-rtsopts=-N"
"-main-is Main"
]
++ commonGhcFlags;
noHaddockOptions = "";
commonGhcFlags = [
"-i./src"
"-threaded"
"-rtsopts"
"-with-rtsopts=-N"
"-main-is Main"
];
ghcPackages = p: [
];
buildDeps = [
pkgs.egl-wayland
pkgs.libGL
pkgs.libxkbcommon
pkgs.wayland
pkgs.xorg.libX11
pkgs.xorg.libXcursor
pkgs.xorg.libXi
pkgs.xorg.libXrandr
];
runtimeDeps = [
pkgs.makeWrapper
pkgs.pkg-config
pkgs.wayland-protocols
pkgs.wayland-scanner
];
in {
packages.${system} = {
debug = pkgs.callPackage ./package.nix {
ghcOptions = debugGhcOptions;
haddockOptions = noHaddockOptions;
inherit ghcPackages;
inherit buildDeps;
inherit runtimeDeps;
default = pkgs.haskellPackages.callPackage package {
xcursor = pkgs.xorg.libXcursor;
xi = pkgs.xorg.libXi;
};
release = pkgs.callPackage ./package.nix {
ghcOptions = releaseGhcOptions;
haddockOptions = noHaddockOptions;
inherit ghcPackages;
inherit buildDeps;
inherit runtimeDeps;
};
docs = pkgs.callPackage ./package.nix {
ghcOptions = "--version";
inherit haddockOptions;
inherit ghcPackages;
inherit buildDeps;
inherit runtimeDeps;
};
default = pkgs.callPackage ./package.nix {
ghcOptions = releaseGhcOptions;
inherit haddockOptions;
inherit ghcPackages;
inherit buildDeps;
inherit runtimeDeps;
};
devShells.${system} = {
default = pkgs.mkShell {
packages = [
pkgs.cabal-install
];
inputsFrom = [
self.packages.${system}.default
];
};
};
};

57
hs-rgfw.cabal Normal file
View File

@@ -0,0 +1,57 @@
cabal-version: 3.0
name: hs-rgfw
-- PVP summary: +-+------- breaking API changes
-- | | +----- non-breaking API additions
-- | | | +--- code changes with no API change
version: 0.1.0.0
-- A short (one-line) description of the package.
-- synopsis:
-- A longer description of the package.
-- description:
homepage: https://git.mtgmonkey.net/Andromeda/hs-rgfw
license: BSD-3-Clause
license-file: LICENSE
author: andromeda
maintainer: @andromeda:tchncs.de
-- A copyright notice.
-- copyright:
category: Development
build-type: Custom
extra-doc-files: CHANGELOG.md
-- Extra source files to be distributed with the package, such as examples, or a tutorial module.
-- extra-source-files:
common warnings
ghc-options:
-Wall
-Widentities
-Wincomplete-record-updates
-Wincomplete-uni-patterns
-Wpartial-fields
-Wredundant-constraints
custom-setup
setup-depends:
base,
Cabal,
process
library
import: warnings
exposed-modules: Lib
-- Modules included in this library but not exported.
-- other-modules:
-- LANGUAGE extensions used by modules in this package.
-- other-extensions:
build-depends:
base >=4.18
pkgconfig-depends:
gl,
wayland-client,
wayland-egl,
wayland-cursor,
xkbcommon,
x11,
xcursor,
xrandr,
xi
hs-source-dirs:
lib
default-language: Haskell2010

View File

@@ -1,40 +1,12 @@
{-# LANGUAGE CApiFFI #-}
module Main (main) where
module Lib where
import Data.Bits (shiftL, (.|.))
import Foreign
import Foreign.C.String
import Foreign.C.Types
--------------------------------------------------------------------------------
-- main
--------------------------------------------------------------------------------
main :: IO ()
main = do
window <- withCString "a window" (\name ->
rgfwCreateWindow
name
0
0
800
600
$ mkWindowFlags
[ WindowNoResize
, WindowOpenGL
, WindowFullscreen
]
)
let loop ctr = do
shouldClose <- rgfwWindowShouldClose window
if 0 /= shouldClose
then return shouldClose
else loop $ ctr + 1
exitCode <- loop 0
putStrLn $ show exitCode
return ()
--------------------------------------------------------------------------------
-- Haskell-ier abstractions
--------------------------------------------------------------------------------
@@ -101,7 +73,7 @@ type RGFWwindowFlags = Word32
type RGFWbool = CUInt
foreign import capi "lib/RGFW_HS.h RGFW_createWindow" rgfwCreateWindow
foreign import capi "RGFW_HS.h RGFW_createWindow" rgfwCreateWindow
:: Ptr CChar
-> CInt
-> CInt
@@ -110,6 +82,6 @@ foreign import capi "lib/RGFW_HS.h RGFW_createWindow" rgfwCreateWindow
-> RGFWwindowFlags
-> IO RGFWwindowPtr
foreign import capi "lib/RGFW_HS.h RGFW_window_shouldClose" rgfwWindowShouldClose
foreign import capi "RGFW_HS.h RGFW_window_shouldClose" rgfwWindowShouldClose
:: RGFWwindowPtr
-> IO RGFWbool

38
lib/Main.hs Normal file
View File

@@ -0,0 +1,38 @@
{-# LANGUAGE CApiFFI #-}
module Main (main) where
import Data.Bits (shiftL, (.|.))
import Foreign
import Foreign.C.String
import Foreign.C.Types
import Lib
--------------------------------------------------------------------------------
-- main
--------------------------------------------------------------------------------
main :: IO ()
main = do
window <- withCString "a window" (\name ->
rgfwCreateWindow
name
0
0
800
600
$ mkWindowFlags
[ WindowNoResize
, WindowOpenGL
, WindowFullscreen
]
)
let loop ctr = do
shouldClose <- rgfwWindowShouldClose window
if 0 /= shouldClose
then return shouldClose
else loop $ ctr + 1
exitCode <- loop 0
putStrLn $ show exitCode
return ()

Submodule lib/RGFW deleted from b7bd582eb3

14034
lib/RGFW.h Normal file

File diff suppressed because it is too large Load Diff

View File

@@ -10,7 +10,7 @@
#define RGFW_OPENGL
#define Time X11Time // fixes namespace clash with GHC when building with Nix
#include "RGFW/RGFW.h"
#include "RGFW.h"
#undef Time
#endif RGFW_HS

View File

@@ -1,66 +0,0 @@
{
buildDeps,
runtimeDeps,
haskellPackages,
lib,
pkgs,
stdenv,
ghcOptions,
haddockOptions,
ghcPackages,
...
}:
stdenv.mkDerivation rec {
pname = "hs-rgfw";
version = "0.1.0";
src = ./.;
nativeBuildInputs =
[
(haskellPackages.ghcWithPackages ghcPackages)
]
++ buildDeps ++ runtimeDeps;
buildInputs =
[
]
++ runtimeDeps;
configurePhase = ''
export PKG_CONFIG_PATH=/run/current-system/sw/lib/pkgconfig
mkdir ccode
wayland-scanner public-code ${pkgs.wayland-protocols}/share/wayland-protocols/stable/xdg-shell/xdg-shell.xml ./ccode/xdg-shell.c
wayland-scanner public-code ${pkgs.wayland-protocols}/share/wayland-protocols/staging/xdg-toplevel-icon/xdg-toplevel-icon-v1.xml ./ccode/xdg-toplevel-icon-v1.c
wayland-scanner public-code ${pkgs.wayland-protocols}/share/wayland-protocols/unstable/xdg-decoration/xdg-decoration-unstable-v1.xml ./ccode/xdg-decoration-unstable-v1.c
wayland-scanner public-code ${pkgs.wayland-protocols}/share/wayland-protocols/unstable/relative-pointer/relative-pointer-unstable-v1.xml ./ccode/relative-pointer-unstable-v1.c
wayland-scanner public-code ${pkgs.wayland-protocols}/share/wayland-protocols/unstable/pointer-constraints/pointer-constraints-unstable-v1.xml ./ccode/pointer-constraints-unstable-v1.c
wayland-scanner public-code ${pkgs.wayland-protocols}/share/wayland-protocols/unstable/xdg-output/xdg-output-unstable-v1.xml ./ccode/xdg-output-unstable-v1.c
mkdir headers
wayland-scanner client-header ${pkgs.wayland-protocols}/share/wayland-protocols/stable/xdg-shell/xdg-shell.xml ./headers/xdg-shell.h
wayland-scanner client-header ${pkgs.wayland-protocols}/share/wayland-protocols/staging/xdg-toplevel-icon/xdg-toplevel-icon-v1.xml ./headers/xdg-toplevel-icon-v1.h
wayland-scanner client-header ${pkgs.wayland-protocols}/share/wayland-protocols/unstable/xdg-decoration/xdg-decoration-unstable-v1.xml ./headers/xdg-decoration-unstable-v1.h
wayland-scanner client-header ${pkgs.wayland-protocols}/share/wayland-protocols/unstable/relative-pointer/relative-pointer-unstable-v1.xml ./headers/relative-pointer-unstable-v1.h
wayland-scanner client-header ${pkgs.wayland-protocols}/share/wayland-protocols/unstable/pointer-constraints/pointer-constraints-unstable-v1.xml ./headers/pointer-constraints-unstable-v1.h
wayland-scanner client-header ${pkgs.wayland-protocols}/share/wayland-protocols/unstable/xdg-output/xdg-output-unstable-v1.xml ./headers/xdg-output-unstable-v1.h
'';
buildPhase = ''
mkdir src/lib
cp -r lib/* src/lib/
cp ccode/*.c ./
ghc ${ghcOptions} ./src/Main.hs -o ./Main $(pkg-config --cflags --libs gl wayland-client wayland-egl wayland-cursor xkbcommon x11 xcursor xrandr xi) -I./headers/ $(ls *.c)
mkdir ./docs
haddock ${haddockOptions}
'';
installPhase = ''
mkdir -p $out/bin
cp ./Main $out/bin/hs-rgfw
cp ./docs $out/docs -r
wrapProgram "$out/bin/${meta.mainProgram}" --prefix LD_LIBRARY_PATH : "${lib.makeLibraryPath buildInputs}"
'';
meta = {
homepage = "https://mtgmonkey.net";
license = lib.licenses.bsd3;
mainProgram = "hs-rgfw";
platforms = ["x86_64-linux"];
};
}

13
scripts/delete-generated.sh Executable file
View File

@@ -0,0 +1,13 @@
rm lib/xdg-shell.h
rm lib/xdg-shell.c
rm lib/xdg-decoration-unstable-v1.h
rm lib/xdg-toplevel-icon-v1.c
rm lib/xdg-toplevel-icon-v1.h
rm lib/xdg-decoration-unstable-v1.c
rm lib/relative-pointer-unstable-v1.h
rm lib/relative-pointer-unstable-v1.c
rm lib/pointer-constraints-unstable-v1.h
rm lib/pointer-constraints-unstable-v1.c
rm lib/xdg-output-unstable-v1.h
rm lib/xdg-output-unstable-v1.c
true

13
scripts/generate.sh Executable file
View File

@@ -0,0 +1,13 @@
wayland-scanner client-header /usr/share/wayland-protocols/stable/xdg-shell/xdg-shell.xml lib/xdg-shell.h
wayland-scanner public-code /usr/share/wayland-protocols/stable/xdg-shell/xdg-shell.xml lib/xdg-shell.c
wayland-scanner client-header /usr/share/wayland-protocols/unstable/xdg-decoration/xdg-decoration-unstable-v1.xml lib/xdg-decoration-unstable-v1.h
wayland-scanner public-code /usr/share/wayland-protocols/staging/xdg-toplevel-icon/xdg-toplevel-icon-v1.xml lib/xdg-toplevel-icon-v1.c
wayland-scanner client-header /usr/share/wayland-protocols/staging/xdg-toplevel-icon/xdg-toplevel-icon-v1.xml lib/xdg-toplevel-icon-v1.h
wayland-scanner public-code /usr/share/wayland-protocols/unstable/xdg-decoration/xdg-decoration-unstable-v1.xml lib/xdg-decoration-unstable-v1.c
wayland-scanner client-header /usr/share/wayland-protocols/unstable/relative-pointer/relative-pointer-unstable-v1.xml lib/relative-pointer-unstable-v1.h
wayland-scanner public-code /usr/share/wayland-protocols/unstable/relative-pointer/relative-pointer-unstable-v1.xml lib/relative-pointer-unstable-v1.c
wayland-scanner client-header /usr/share/wayland-protocols/unstable/pointer-constraints/pointer-constraints-unstable-v1.xml lib/pointer-constraints-unstable-v1.h
wayland-scanner public-code /usr/share/wayland-protocols/unstable/pointer-constraints/pointer-constraints-unstable-v1.xml lib/pointer-constraints-unstable-v1.c
wayland-scanner client-header /usr/share/wayland-protocols/unstable/xdg-output/xdg-output-unstable-v1.xml lib/xdg-output-unstable-v1.h
wayland-scanner public-code /usr/share/wayland-protocols/unstable/xdg-output/xdg-output-unstable-v1.xml lib/xdg-output-unstable-v1.c
true