update
This commit is contained in:
commit
a1d15f184c
9 changed files with 588 additions and 0 deletions
2
.gitignore
vendored
Normal file
2
.gitignore
vendored
Normal file
|
@ -0,0 +1,2 @@
|
|||
/.zig-cache
|
||||
/zig-out
|
63
build.zig
Normal file
63
build.zig
Normal file
|
@ -0,0 +1,63 @@
|
|||
const std = @import("std");
|
||||
const Scanner = @import("wayland").Scanner;
|
||||
|
||||
pub fn build(b: *std.Build) void {
|
||||
const target = b.standardTargetOptions(.{});
|
||||
const optimize = b.standardOptimizeOption(.{});
|
||||
|
||||
const gdbus = b.option([]const u8, "gdbus", "path to gdbus binary") orelse {
|
||||
return;
|
||||
};
|
||||
|
||||
const build_options = b.addOptions();
|
||||
build_options.addOption([]const u8, "gdbus", gdbus);
|
||||
|
||||
const scanner = Scanner.create(b, .{});
|
||||
const wayland = b.createModule(.{ .root_source_file = scanner.result });
|
||||
|
||||
scanner.addCustomProtocol("src/river/river-control-unstable-v1.xml");
|
||||
scanner.addCustomProtocol("src/river/river-status-unstable-v1.xml");
|
||||
|
||||
scanner.generate("wl_output", 4);
|
||||
scanner.generate("wl_seat", 7);
|
||||
scanner.generate("zriver_control_v1", 1);
|
||||
scanner.generate("zriver_status_manager_v1", 1);
|
||||
|
||||
const exe = b.addExecutable(.{
|
||||
.name = "init",
|
||||
.root_source_file = b.path("src/main.zig"),
|
||||
.target = target,
|
||||
.optimize = optimize,
|
||||
});
|
||||
|
||||
exe.root_module.addImport("wayland", wayland);
|
||||
exe.linkSystemLibrary2("wayland-client", .{});
|
||||
exe.linkLibC();
|
||||
scanner.addCSource(exe);
|
||||
b.installArtifact(exe);
|
||||
|
||||
const run_cmd = b.addRunArtifact(exe);
|
||||
|
||||
run_cmd.step.dependOn(b.getInstallStep());
|
||||
|
||||
if (b.args) |args| {
|
||||
run_cmd.addArgs(args);
|
||||
}
|
||||
|
||||
const run_step = b.step("run", "Run the app");
|
||||
run_step.dependOn(&run_cmd.step);
|
||||
|
||||
const exe_unit_tests = b.addTest(.{
|
||||
.root_source_file = b.path("src/main.zig"),
|
||||
.target = target,
|
||||
.optimize = optimize,
|
||||
});
|
||||
|
||||
const run_exe_unit_tests = b.addRunArtifact(exe_unit_tests);
|
||||
|
||||
// Similar to creating the run step earlier, this exposes a `test` step to
|
||||
// the `zig build --help` menu, providing a way for the user to request
|
||||
// running the unit tests.
|
||||
const test_step = b.step("test", "Run unit tests");
|
||||
test_step.dependOn(&run_exe_unit_tests.step);
|
||||
}
|
24
build.zig.zon
Normal file
24
build.zig.zon
Normal file
|
@ -0,0 +1,24 @@
|
|||
.{
|
||||
.name = "river-init",
|
||||
|
||||
.version = "0.0.0",
|
||||
|
||||
.minimum_zig_version = "0.13.0",
|
||||
|
||||
.dependencies = .{
|
||||
.wayland = .{
|
||||
.url = "git+https://codeberg.org/ifreund/zig-wayland.git?ref=master#b72ef788eb5da9957c21cc50772e3ff7bc77a69d",
|
||||
.hash = "122008883160591808fa8244b73fe893ac696efb2aa0dcdc88b9c1fbff1703aada73",
|
||||
},
|
||||
.river = .{
|
||||
.url = "git+https://codeberg.org/river/river.git?ref=main#26f599b56b8f73dc13be055f6730edafd6c30401",
|
||||
.hash = "122023df5bc57c7c8d6e43e714b01afab2104f714fb65d60a50e0a6e543490ad46f7",
|
||||
},
|
||||
},
|
||||
|
||||
.paths = .{
|
||||
"build.zig",
|
||||
"build.zig.zon",
|
||||
"src",
|
||||
},
|
||||
}
|
60
flake.lock
generated
Normal file
60
flake.lock
generated
Normal file
|
@ -0,0 +1,60 @@
|
|||
{
|
||||
"nodes": {
|
||||
"flake-utils": {
|
||||
"inputs": {
|
||||
"systems": "systems"
|
||||
},
|
||||
"locked": {
|
||||
"lastModified": 1726560853,
|
||||
"narHash": "sha256-X6rJYSESBVr3hBoH0WbKE5KvhPU5bloyZ2L4K60/fPQ=",
|
||||
"owner": "numtide",
|
||||
"repo": "flake-utils",
|
||||
"rev": "c1dfcf08411b08f6b8615f7d8971a2bfa81d5e8a",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
"owner": "numtide",
|
||||
"repo": "flake-utils",
|
||||
"type": "github"
|
||||
}
|
||||
},
|
||||
"nixpkgs": {
|
||||
"locked": {
|
||||
"lastModified": 1726937504,
|
||||
"narHash": "sha256-bvGoiQBvponpZh8ClUcmJ6QnsNKw0EMrCQJARK3bI1c=",
|
||||
"owner": "NixOS",
|
||||
"repo": "nixpkgs",
|
||||
"rev": "9357f4f23713673f310988025d9dc261c20e70c6",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
"id": "nixpkgs",
|
||||
"ref": "nixos-unstable",
|
||||
"type": "indirect"
|
||||
}
|
||||
},
|
||||
"root": {
|
||||
"inputs": {
|
||||
"flake-utils": "flake-utils",
|
||||
"nixpkgs": "nixpkgs"
|
||||
}
|
||||
},
|
||||
"systems": {
|
||||
"locked": {
|
||||
"lastModified": 1681028828,
|
||||
"narHash": "sha256-Vy1rq5AaRuLzOxct8nz4T6wlgyUR7zLU309k9mBC768=",
|
||||
"owner": "nix-systems",
|
||||
"repo": "default",
|
||||
"rev": "da67096a3b9bf56a91d16901293e51ba5b49a27e",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
"owner": "nix-systems",
|
||||
"repo": "default",
|
||||
"type": "github"
|
||||
}
|
||||
}
|
||||
},
|
||||
"root": "root",
|
||||
"version": 7
|
||||
}
|
92
flake.nix
Normal file
92
flake.nix
Normal file
|
@ -0,0 +1,92 @@
|
|||
{
|
||||
inputs = {
|
||||
nixpkgs = {
|
||||
url = "nixpkgs/nixos-unstable";
|
||||
};
|
||||
flake-utils = {
|
||||
url = "github:numtide/flake-utils";
|
||||
};
|
||||
};
|
||||
|
||||
outputs = {
|
||||
nixpkgs,
|
||||
flake-utils,
|
||||
...
|
||||
}:
|
||||
flake-utils.lib.eachDefaultSystem (
|
||||
system: let
|
||||
pkgs = import nixpkgs {
|
||||
inherit system;
|
||||
};
|
||||
in {
|
||||
devShells = {
|
||||
default = pkgs.mkShell {
|
||||
nativeBuildInputs = [
|
||||
pkgs.zig_0_13
|
||||
pkgs.pkg-config
|
||||
pkgs.wayland-protocols
|
||||
pkgs.wayland-scanner
|
||||
];
|
||||
buildInputs = [
|
||||
pkgs.wayland
|
||||
];
|
||||
shellHook = ''
|
||||
export name=river-init
|
||||
'';
|
||||
};
|
||||
};
|
||||
packages = {
|
||||
zmodem = let
|
||||
cache = src:
|
||||
pkgs.stdenv.mkDerivation {
|
||||
inherit src;
|
||||
name = "river-init-cache";
|
||||
nativeBuildInputs = [
|
||||
pkgs.git
|
||||
pkgs.pkg-config
|
||||
pkgs.wayland-protocols
|
||||
pkgs.wayland-scanner
|
||||
pkgs.zig_0_13.hook
|
||||
];
|
||||
buildInputs = [
|
||||
pkgs.wayland
|
||||
];
|
||||
|
||||
dontConfigure = true;
|
||||
dontUseZigBuild = true;
|
||||
dontUseZigInstall = true;
|
||||
dontFixup = true;
|
||||
|
||||
buildPhase = ''
|
||||
runHook preBuild
|
||||
zig build --fetch
|
||||
runHook postBuild
|
||||
'';
|
||||
|
||||
installPhase = ''
|
||||
runHook preInstall
|
||||
cp -r --reflink=auto $ZIG_GLOBAL_CACHE_DIR $out
|
||||
runHook postInstall
|
||||
'';
|
||||
|
||||
outputHashMode = "recursive";
|
||||
outputHash = pkgs.lib.fakeHash;
|
||||
};
|
||||
in
|
||||
pkgs.stdenv.mkDerivation (final: {
|
||||
pname = "river-init";
|
||||
version = "0.0.0";
|
||||
src = ./.;
|
||||
nativeBuildInputs = [
|
||||
pkgs.zig_0_13.hook
|
||||
];
|
||||
preBuild = ''
|
||||
rm -rf $ZIG_GLOBAL_CACHE_DIR
|
||||
cp -r --reflink=auto ${cache final.src} $ZIG_GLOBAL_CACHE_DIR
|
||||
chmod u+rwX -R $ZIG_GLOBAL_CACHE_DIR
|
||||
'';
|
||||
});
|
||||
};
|
||||
}
|
||||
);
|
||||
}
|
104
src/main.zig
Normal file
104
src/main.zig
Normal file
|
@ -0,0 +1,104 @@
|
|||
const std = @import("std");
|
||||
const wayland = @import("wayland");
|
||||
|
||||
const wl = wayland.client.wl;
|
||||
const zriver = wayland.client.zriver;
|
||||
|
||||
pub fn main() !void {
|
||||
_main() catch |err| {
|
||||
switch (err) {
|
||||
error.RiverControlNotAdvertised => fatal(
|
||||
\\The Wayland server does not support river-control-unstable-v1.
|
||||
\\Do your versions of river and riverctl match?
|
||||
, .{}),
|
||||
error.RiverStatusManagerNotAdvertised => fatal(
|
||||
\\The Wayland server does not support river-status-unstable-v1.
|
||||
\\Do your versions of river and riverctl match?
|
||||
, .{}),
|
||||
error.SeatNotAdverstised => fatal(
|
||||
\\The Wayland server did not advertise any seat.
|
||||
, .{}),
|
||||
error.OutputNotAdverstised => fatal(
|
||||
\\The Wayland server did not advertise any output.
|
||||
, .{}),
|
||||
error.ConnectFailed => {
|
||||
std.log.err("Unable to connect to the Wayland server.", .{});
|
||||
if (std.posix.getenvZ("WAYLAND_DISPLAY") == null) {
|
||||
fatal("WAYLAND_DISPLAY is not set.", .{});
|
||||
} else {
|
||||
fatal("Does WAYLAND_DISPLAY contain the socket name of a running server?", .{});
|
||||
}
|
||||
},
|
||||
else => return err,
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
pub const Globals = struct {
|
||||
control: ?*zriver.ControlV1 = null,
|
||||
status_manager: ?*zriver.StatusManagerV1 = null,
|
||||
output: ?*wl.Output = null,
|
||||
seat: ?*wl.Seat = null,
|
||||
};
|
||||
|
||||
fn _main() !void {
|
||||
const display = try wl.Display.connect(null);
|
||||
const registry = try display.getRegistry();
|
||||
var globals = Globals{};
|
||||
registry.setListener(*Globals, registryListener, &globals);
|
||||
if (display.roundtrip() != .SUCCESS) fatal("initial roundtrip failed", .{});
|
||||
const control = globals.control orelse return error.RiverControlNotAdvertised;
|
||||
_ = globals.status_manager orelse return error.RiverStatusManagerNotAdvertised;
|
||||
_ = globals.seat orelse return error.SeatNotAdverstised;
|
||||
_ = globals.output orelse return error.OutputNotAdverstised;
|
||||
|
||||
control.addArgument("map");
|
||||
control.addArgument("Super");
|
||||
control.addArgument("G");
|
||||
control.addArgument("spawn");
|
||||
control.addArgument("gdbus call --session --dest com.mitchellh.ghostty --object-path /com/mitchellh/ghostty --method org.gtk.Actions.Activate new_window [] []'");
|
||||
}
|
||||
|
||||
fn registryListener(registry: *wl.Registry, event: wl.Registry.Event, globals: *Globals) void {
|
||||
switch (event) {
|
||||
.global => |global| {
|
||||
if (std.mem.orderZ(u8, global.interface, wl.Seat.getInterface().name) == .eq) {
|
||||
std.debug.assert(globals.seat == null); // TODO: support multiple seats
|
||||
globals.seat = registry.bind(global.name, wl.Seat, global.version) catch @panic("out of memory");
|
||||
} else if (std.mem.orderZ(u8, global.interface, wl.Output.getInterface().name) == .eq) {
|
||||
globals.output = registry.bind(global.name, wl.Output, global.version) catch @panic("out of memory");
|
||||
} else if (std.mem.orderZ(u8, global.interface, zriver.ControlV1.getInterface().name) == .eq) {
|
||||
globals.control = registry.bind(global.name, zriver.ControlV1, global.version) catch @panic("out of memory");
|
||||
} else if (std.mem.orderZ(u8, global.interface, zriver.StatusManagerV1.getInterface().name) == .eq) {
|
||||
globals.status_manager = registry.bind(global.name, zriver.StatusManagerV1, global.version) catch @panic("out of memory");
|
||||
}
|
||||
},
|
||||
.global_remove => {},
|
||||
}
|
||||
}
|
||||
|
||||
fn callbackListener(_: *zriver.CommandCallbackV1, event: zriver.CommandCallbackV1.Event, _: ?*anyopaque) void {
|
||||
switch (event) {
|
||||
.success => |success| {
|
||||
if (std.mem.len(success.output) > 0) {
|
||||
const stdout = std.io.getStdOut().writer();
|
||||
stdout.print("{s}\n", .{success.output}) catch @panic("failed to write to stdout");
|
||||
}
|
||||
std.posix.exit(0);
|
||||
},
|
||||
.failure => |failure| {
|
||||
// A small hack to provide usage text when river reports an unknown command.
|
||||
if (std.mem.orderZ(u8, failure.failure_message, "unknown command") == .eq) {
|
||||
std.log.err("unknown command", .{});
|
||||
std.io.getStdErr().writeAll("blah blah blah") catch {};
|
||||
std.posix.exit(1);
|
||||
}
|
||||
fatal("{s}", .{failure.failure_message});
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
fn fatal(comptime format: []const u8, args: anytype) noreturn {
|
||||
std.log.err(format, args);
|
||||
std.posix.exit(1);
|
||||
}
|
85
src/river/river-control-unstable-v1.xml
Normal file
85
src/river/river-control-unstable-v1.xml
Normal file
|
@ -0,0 +1,85 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<protocol name="river_control_unstable_v1">
|
||||
<copyright>
|
||||
Copyright 2020 The River Developers
|
||||
|
||||
Permission to use, copy, modify, and/or distribute this software for any
|
||||
purpose with or without fee is hereby granted, provided that the above
|
||||
copyright notice and this permission notice appear in all copies.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
</copyright>
|
||||
|
||||
<interface name="zriver_control_v1" version="1">
|
||||
<description summary="run compositor commands">
|
||||
This interface allows clients to run compositor commands and receive a
|
||||
success/failure response with output or a failure message respectively.
|
||||
|
||||
Each command is built up in a series of add_argument requests and
|
||||
executed with a run_command request. The first argument is the command
|
||||
to be run.
|
||||
|
||||
A complete list of commands should be made available in the man page of
|
||||
the compositor.
|
||||
</description>
|
||||
|
||||
<request name="destroy" type="destructor">
|
||||
<description summary="destroy the river_control object">
|
||||
This request indicates that the client will not use the
|
||||
river_control object any more. Objects that have been created
|
||||
through this instance are not affected.
|
||||
</description>
|
||||
</request>
|
||||
|
||||
<request name="add_argument">
|
||||
<description summary="add an argument to the current command">
|
||||
Arguments are stored by the server in the order they were sent until
|
||||
the run_command request is made.
|
||||
</description>
|
||||
<arg name="argument" type="string" summary="the argument to add"/>
|
||||
</request>
|
||||
|
||||
<request name="run_command">
|
||||
<description summary="run the current command">
|
||||
Execute the command built up using the add_argument request for the
|
||||
given seat.
|
||||
</description>
|
||||
<arg name="seat" type="object" interface="wl_seat"/>
|
||||
<arg name="callback" type="new_id" interface="zriver_command_callback_v1"
|
||||
summary="callback object"/>
|
||||
</request>
|
||||
</interface>
|
||||
|
||||
<interface name="zriver_command_callback_v1" version="1">
|
||||
<description summary="callback object">
|
||||
This object is created by the run_command request. Exactly one of the
|
||||
success or failure events will be sent. This object will be destroyed
|
||||
by the compositor after one of the events is sent.
|
||||
</description>
|
||||
|
||||
<event name="success" type="destructor">
|
||||
<description summary="command successful">
|
||||
Sent when the command has been successfully received and executed by
|
||||
the compositor. Some commands may produce output, in which case the
|
||||
output argument will be a non-empty string.
|
||||
</description>
|
||||
<arg name="output" type="string" summary="the output of the command"/>
|
||||
</event>
|
||||
|
||||
<event name="failure" type="destructor">
|
||||
<description summary="command failed">
|
||||
Sent when the command could not be carried out. This could be due to
|
||||
sending a non-existent command, no command, not enough arguments, too
|
||||
many arguments, invalid arguments, etc.
|
||||
</description>
|
||||
<arg name="failure_message" type="string"
|
||||
summary="a message explaining why failure occurred"/>
|
||||
</event>
|
||||
</interface>
|
||||
</protocol>
|
148
src/river/river-status-unstable-v1.xml
Normal file
148
src/river/river-status-unstable-v1.xml
Normal file
|
@ -0,0 +1,148 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<protocol name="river_status_unstable_v1">
|
||||
<copyright>
|
||||
Copyright 2020 The River Developers
|
||||
|
||||
Permission to use, copy, modify, and/or distribute this software for any
|
||||
purpose with or without fee is hereby granted, provided that the above
|
||||
copyright notice and this permission notice appear in all copies.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
</copyright>
|
||||
|
||||
<interface name="zriver_status_manager_v1" version="4">
|
||||
<description summary="manage river status objects">
|
||||
A global factory for objects that receive status information specific
|
||||
to river. It could be used to implement, for example, a status bar.
|
||||
</description>
|
||||
|
||||
<request name="destroy" type="destructor">
|
||||
<description summary="destroy the river_status_manager object">
|
||||
This request indicates that the client will not use the
|
||||
river_status_manager object any more. Objects that have been created
|
||||
through this instance are not affected.
|
||||
</description>
|
||||
</request>
|
||||
|
||||
<request name="get_river_output_status">
|
||||
<description summary="create an output status object">
|
||||
This creates a new river_output_status object for the given wl_output.
|
||||
</description>
|
||||
<arg name="id" type="new_id" interface="zriver_output_status_v1"/>
|
||||
<arg name="output" type="object" interface="wl_output"/>
|
||||
</request>
|
||||
|
||||
<request name="get_river_seat_status">
|
||||
<description summary="create a seat status object">
|
||||
This creates a new river_seat_status object for the given wl_seat.
|
||||
</description>
|
||||
<arg name="id" type="new_id" interface="zriver_seat_status_v1"/>
|
||||
<arg name="seat" type="object" interface="wl_seat"/>
|
||||
</request>
|
||||
</interface>
|
||||
|
||||
<interface name="zriver_output_status_v1" version="4">
|
||||
<description summary="track output tags and focus">
|
||||
This interface allows clients to receive information about the current
|
||||
windowing state of an output.
|
||||
</description>
|
||||
|
||||
<request name="destroy" type="destructor">
|
||||
<description summary="destroy the river_output_status object">
|
||||
This request indicates that the client will not use the
|
||||
river_output_status object any more.
|
||||
</description>
|
||||
</request>
|
||||
|
||||
<event name="focused_tags">
|
||||
<description summary="focused tags of the output">
|
||||
Sent once binding the interface and again whenever the tag focus of
|
||||
the output changes.
|
||||
</description>
|
||||
<arg name="tags" type="uint" summary="32-bit bitfield"/>
|
||||
</event>
|
||||
|
||||
<event name="view_tags">
|
||||
<description summary="tag state of an output's views">
|
||||
Sent once on binding the interface and again whenever the tag state
|
||||
of the output changes.
|
||||
</description>
|
||||
<arg name="tags" type="array" summary="array of 32-bit bitfields"/>
|
||||
</event>
|
||||
|
||||
<event name="urgent_tags" since="2">
|
||||
<description summary="tags of the output with an urgent view">
|
||||
Sent once on binding the interface and again whenever the set of
|
||||
tags with at least one urgent view changes.
|
||||
</description>
|
||||
<arg name="tags" type="uint" summary="32-bit bitfield"/>
|
||||
</event>
|
||||
|
||||
<event name="layout_name" since="4">
|
||||
<description summary="name of the layout">
|
||||
Sent once on binding the interface should a layout name exist and again
|
||||
whenever the name changes.
|
||||
</description>
|
||||
<arg name="name" type="string" summary="layout name"/>
|
||||
</event>
|
||||
|
||||
<event name="layout_name_clear" since="4">
|
||||
<description summary="name of the layout">
|
||||
Sent when the current layout name has been removed without a new one
|
||||
being set, for example when the active layout generator disconnects.
|
||||
</description>
|
||||
</event>
|
||||
</interface>
|
||||
|
||||
<interface name="zriver_seat_status_v1" version="3">
|
||||
<description summary="track seat focus">
|
||||
This interface allows clients to receive information about the current
|
||||
focus of a seat. Note that (un)focused_output events will only be sent
|
||||
if the client has bound the relevant wl_output globals.
|
||||
</description>
|
||||
|
||||
<request name="destroy" type="destructor">
|
||||
<description summary="destroy the river_seat_status object">
|
||||
This request indicates that the client will not use the
|
||||
river_seat_status object any more.
|
||||
</description>
|
||||
</request>
|
||||
|
||||
<event name="focused_output">
|
||||
<description summary="the seat focused an output">
|
||||
Sent on binding the interface and again whenever an output gains focus.
|
||||
</description>
|
||||
<arg name="output" type="object" interface="wl_output"/>
|
||||
</event>
|
||||
|
||||
<event name="unfocused_output">
|
||||
<description summary="the seat unfocused an output">
|
||||
Sent whenever an output loses focus.
|
||||
</description>
|
||||
<arg name="output" type="object" interface="wl_output"/>
|
||||
</event>
|
||||
|
||||
<event name="focused_view">
|
||||
<description summary="information on the focused view">
|
||||
Sent once on binding the interface and again whenever the focused
|
||||
view or a property thereof changes. The title may be an empty string
|
||||
if no view is focused or the focused view did not set a title.
|
||||
</description>
|
||||
<arg name="title" type="string" summary="title of the focused view"/>
|
||||
</event>
|
||||
|
||||
<event name="mode" since="3">
|
||||
<description summary="the active mode changed">
|
||||
Sent once on binding the interface and again whenever a new mode
|
||||
is entered (e.g. with riverctl enter-mode foobar).
|
||||
</description>
|
||||
<arg name="name" type="string" summary="name of the mode"/>
|
||||
</event>
|
||||
</interface>
|
||||
</protocol>
|
10
src/root.zig
Normal file
10
src/root.zig
Normal file
|
@ -0,0 +1,10 @@
|
|||
const std = @import("std");
|
||||
const testing = std.testing;
|
||||
|
||||
export fn add(a: i32, b: i32) i32 {
|
||||
return a + b;
|
||||
}
|
||||
|
||||
test "basic add functionality" {
|
||||
try testing.expect(add(3, 7) == 10);
|
||||
}
|
Loading…
Add table
Reference in a new issue