diff --git a/.gitignore b/.gitignore index 0c8ed5f..d277caf 100644 --- a/.gitignore +++ b/.gitignore @@ -3,3 +3,5 @@ zig-out/ build/ build-*/ docgen_tmp/ +.cache/ +.direnv/ diff --git a/triangle/.clangd b/triangle/.clangd new file mode 100644 index 0000000..be204da --- /dev/null +++ b/triangle/.clangd @@ -0,0 +1,3 @@ +CompileFlags: + Add: + - $(pkg-config --cflags wayland-client) diff --git a/triangle/.envrc b/triangle/.envrc new file mode 100644 index 0000000..3550a30 --- /dev/null +++ b/triangle/.envrc @@ -0,0 +1 @@ +use flake diff --git a/triangle/build.zig b/triangle/build.zig index dfccdd7..c0ef36e 100644 --- a/triangle/build.zig +++ b/triangle/build.zig @@ -7,15 +7,17 @@ pub fn build(b: *std.Build) void { // add the C source file to the build const exe = b.addExecutable(.{ .name = "triangle", + .root_source_file = b.path("src/main.zig"), .target = target, .optimize = mode, }); + + // add c libraries exe.linkLibC(); - exe.addCSourceFiles(.{ - .files = &.{ - "src/main.c", - }, - }); + + // add wayland-client + exe.linkSystemLibrary("wayland-client"); + b.installArtifact(exe); const run_exe = b.addRunArtifact(exe); diff --git a/triangle/flake.nix b/triangle/flake.nix index 1423502..ba2ba9f 100644 --- a/triangle/flake.nix +++ b/triangle/flake.nix @@ -10,11 +10,22 @@ pkgs = nixpkgs.legacyPackages.x86_64-linux; in { - devShells.x86_64-linux.default = pkgs.mkShell { + devShells.x86_64-linux.default = pkgs.mkShell.override { stdenv = pkgs.clangStdenv; } { name = "triangle"; packages = with pkgs; [ zig # used to compile c ]; + buildInputs = with pkgs; [ + wayland # used to show the window on wayland + ]; + nativeBuildInputs = with pkgs; [ + pkg-config # used to find wayland + wayland-scanner + ]; + shellHook = '' + export LD_LIBRARY_PATH=${(pkgs.lib.makeLibraryPath [ pkgs.wayland ])}:$LD_LIBRARY_PATH + export LIBRARY_PATH=${(pkgs.lib.makeLibraryPath [ pkgs.wayland ])}:$LIBRARY_PATH + ''; }; }; } diff --git a/triangle/src/main.c b/triangle/src/main.c deleted file mode 100644 index 0923337..0000000 --- a/triangle/src/main.c +++ /dev/null @@ -1,6 +0,0 @@ -#include - -int main() { - printf("Hello, World!\n"); - return 0; -} diff --git a/triangle/src/main.zig b/triangle/src/main.zig new file mode 100644 index 0000000..232d84b --- /dev/null +++ b/triangle/src/main.zig @@ -0,0 +1,84 @@ +const std = @import("std"); +const wayland = @cImport({ + @cInclude("wayland-client.h"); +}); +const cString = @cImport({ + @cInclude("string.h"); +}); +const cStdio = @cImport({ + @cInclude("stdio.h"); +}); + +var shell: ?*wayland.wl_shell = null; +var compositor: ?*wayland.wl_compositor = null; + +pub fn main() void { + const display = wayland.wl_display_connect(null); + if (display == null) { + std.debug.print("Can't connect to display\n", .{}); + return; + } + + const registry = wayland.wl_display_get_registry(display); + if (registry == null) { + std.debug.print("Can't get registry\n", .{}); + return; + } + + const registryListener = [_]wayland.wl_registry_listener{wayland.wl_registry_listener{ + .global = globalRegistryHandler, + }}; + _ = wayland.wl_registry_add_listener(registry, ®istryListener, null); + + // wait for the registry to be ready and then dispatch the events + std.debug.print("waiting for registry\n", .{}); + _ = wayland.wl_display_dispatch(display); + _ = wayland.wl_display_roundtrip(display); + std.debug.print("finished waiting for registry\n", .{}); + + // make sure the compositor and the shell exists + if (compositor == null) { + std.debug.print("Can't get compositor\n", .{}); + return; + } + if (shell == null) { + std.debug.print("Can't get shell\n", .{}); + return; + } + + // spawn the shell + std.debug.print("spawning shell\n", .{}); + const surface = wayland.wl_compositor_create_surface(compositor); + if (surface == null) { + std.debug.print("Can't get shell surface\n", .{}); + return; + } + + const shell_surface = wayland.wl_shell_get_shell_surface(shell, surface); + wayland.wl_shell_surface_set_toplevel(shell_surface); + + std.debug.print("connected to display\n", .{}); + wayland.wl_display_disconnect(display); + std.debug.print("disconnected from display\n", .{}); +} + +fn globalRegistryHandler(_: ?*anyopaque, registry: ?*wayland.wl_registry, id: u32, interface: ?[*]const u8, version: u32) callconv(.C) void { + _ = cStdio.printf("interface: %s\n", interface); + + if (interface) |iface| { + if (cString.strcmp("wl_compositor", iface) == 0) { + if (registry) |reg| { + std.debug.print("compositor found\n", .{}); + compositor = if (wayland.wl_registry_bind(reg, id, &wayland.wl_compositor_interface, version)) |ptr| @ptrCast(ptr) else null; + } + return; + } + + if (cString.strcmp("xdg_wm_base", iface) == 0) { + if (registry) |reg| { + std.debug.print("shell found\n", .{}); + shell = if (wayland.wl_registry_bind(reg, id, &wayland.wl_compositor_interface, version)) |ptr| @ptrCast(ptr) else null; + } + } + } +}