Split control into separate protocol

This commit is contained in:
Isaac Freund 2020-05-24 20:58:39 +02:00
parent 08a2f47a5e
commit d83cbf55d1
7 changed files with 84 additions and 57 deletions

View file

@ -79,7 +79,7 @@ fn addServerDeps(exe: *std.build.LibExeObjStep) void {
fn addProtocolDeps(exe: *std.build.LibExeObjStep, protocol_step: *std.build.Step) void {
exe.step.dependOn(protocol_step);
exe.addIncludeDir("protocol");
exe.addCSourceFile("protocol/river-window-management-unstable-v1-protocol.c", &[_][]const u8{"-std=c99"});
exe.addCSourceFile("protocol/river-control-unstable-v1-protocol.c", &[_][]const u8{"-std=c99"});
}
const ScanProtocolsStep = struct {
@ -109,7 +109,7 @@ const ScanProtocolsStep = struct {
const protocol_dir_paths = [_][]const []const u8{
&[_][]const u8{ protocol_dir, "stable/xdg-shell/xdg-shell.xml" },
&[_][]const u8{ "protocol", "wlr-layer-shell-unstable-v1.xml" },
&[_][]const u8{ "protocol", "river-window-management-unstable-v1.xml" },
&[_][]const u8{ "protocol", "river-control-unstable-v1.xml" },
};
for (protocol_dir_paths) |dir_path| {
@ -137,8 +137,8 @@ const ScanProtocolsStep = struct {
&[_][]const u8{ "wayland-scanner", "private-code", xml_in_path, code_out_path },
);
// We need the client header as well for river-window-management
if (std.mem.eql(u8, basename_no_ext, "river-window-management-unstable-v1")) {
// We need the client header as well for river-control
if (std.mem.eql(u8, basename_no_ext, "river-control-unstable-v1")) {
const client_header_out_path = try std.mem.concat(
self.builder.allocator,
u8,

View file

@ -0,0 +1,60 @@
<?xml version="1.0" encoding="UTF-8"?>
<protocol name="river_control_unstable_v1">
<copyright>
Copyright 2020 Isaac Freund
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 a failure message if needed.
</description>
<request name="run_command">
<description summary="run a compositor command">
A complete list of commands will be found in the man page for the
compositor.
</description>
<arg name="command" type="array" summary="the command to run as a series
of null-terminated strings"/>
<arg name="callback" type="new_id" interface="zriver_command_callback_v1"
summary="callback object to receive success/error events"/>
</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.
</description>
<event name="success">
<description summary="command successful">
Send when the command has been successfully received and validated by
the server and will be carried out.
</description>
</event>
<event name="failure">
<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>

View file

@ -17,22 +17,12 @@
</copyright>
<interface name="zriver_window_manager_v1" version="1">
<description summary="manage windows and track windowing state">
This protocol allows clients to run windowing commands and recieve
information about the current windowing state.
<description summary="track windowing state">
This protocol allows clients to recieve information about the current
windowing state. It is useful to implement, for example, a status bar
displaying information specific to the river compositor.
</description>
<request name="run_command">
<description summary="run a compositor command">
A complete list of commands will be found in the man page.
TODO: write the man page.
</description>
<arg name="command" type="array" summary="the command to run as a series
of null-terminated strings"/>
<arg name="callback" type="new_id" interface="zriver_command_callback_v1"
summary="callback object to recieve success/error events"/>
</request>
<event name="focus">
<description summary="sent when a view gains focus">
</description>
@ -54,27 +44,4 @@
summary="the current tags of each view on the output"/>
</event>
</interface>
<interface name="zriver_command_callback_v1" version="1">
<description summary="callback object">
Exactly one of the success or failure events will be sent.
</description>
<event name="success">
<description summary="command successful">
Send when the command has been successfully received and validated by
the server and will be carried out.
</description>
</event>
<event name="failure">
<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>

View file

@ -27,7 +27,7 @@ const Server = @import("Server.zig");
const protocol_version = 1;
const implementation = c.struct_zriver_window_manager_v1_interface{
const implementation = c.struct_zriver_control_v1_interface{
.run_command = runCommand,
};
@ -40,7 +40,7 @@ pub fn init(self: *Self, server: *Server) !void {
self.server = server;
self.wl_global = c.wl_global_create(
server.wl_display,
&c.zriver_window_manager_v1_interface,
&c.zriver_control_v1_interface,
protocol_version,
self,
bind,
@ -60,7 +60,7 @@ fn bind(wl_client: ?*c.wl_client, data: ?*c_void, version: u32, id: u32) callcon
const self = @ptrCast(*Self, @alignCast(@alignOf(*Self), data));
const wl_resource = c.wl_resource_create(
wl_client,
&c.zriver_window_manager_v1_interface,
&c.zriver_control_v1_interface,
@intCast(c_int, version),
id,
) orelse {

View file

@ -31,7 +31,7 @@ const Output = @import("Output.zig");
const Root = @import("Root.zig");
const View = @import("View.zig");
const ViewStack = @import("view_stack.zig").ViewStack;
const WindowManager = @import("WindowManager.zig");
const Control = @import("Control.zig");
const XwaylandUnmanaged = @import("XwaylandUnmanaged.zig");
allocator: *std.mem.Allocator,
@ -56,7 +56,7 @@ decoration_manager: DecorationManager,
input_manager: InputManager,
root: Root,
config: Config,
window_manager: WindowManager,
control: Control,
pub fn init(self: *Self, allocator: *std.mem.Allocator) !void {
self.allocator = allocator;
@ -122,7 +122,7 @@ pub fn init(self: *Self, allocator: *std.mem.Allocator) !void {
try self.root.init(self);
// Must be called after root is initialized
try self.input_manager.init(self);
try self.window_manager.init(self);
try self.control.init(self);
// These all free themselves when the wl_display is destroyed
_ = c.wlr_data_device_manager_create(self.wl_display) orelse

View file

@ -48,7 +48,7 @@ pub usingnamespace @cImport({
// that can be automatically imported
@cInclude("include/bindings.h");
@cInclude("river-window-management-unstable-v1-protocol.h");
@cInclude("river-control-unstable-v1-protocol.h");
});
// These are needed because zig currently names translated anonymous unions

View file

@ -19,7 +19,7 @@ const std = @import("std");
const c = @cImport({
@cInclude("wayland-client.h");
@cInclude("river-window-management-unstable-v1-client-protocol.h");
@cInclude("river-control-unstable-v1-client-protocol.h");
});
const wl_registry_listener = c.wl_registry_listener{
@ -32,7 +32,7 @@ const command_callback_listener = c.zriver_command_callback_v1_listener{
.failure = handleFailure,
};
var river_window_manager: ?*c.zriver_window_manager_v1 = null;
var river_control_optional: ?*c.zriver_control_v1 = null;
pub fn main() !void {
const wl_display = c.wl_display_connect(null) orelse return error.CantConnectToDisplay;
@ -42,7 +42,7 @@ pub fn main() !void {
return error.FailedToAddListener;
if (c.wl_display_roundtrip(wl_display) < 0) return error.RoundtripFailed;
const wm = river_window_manager orelse return error.RiverWMNotAdvertised;
const river_control = river_control_optional orelse return error.RiverControlNotAdvertised;
var command: c.wl_array = undefined;
c.wl_array_init(&command);
@ -57,7 +57,7 @@ pub fn main() !void {
ptr[arg.len] = 0;
}
const command_callback = c.zriver_window_manager_v1_run_command(wm, &command);
const command_callback = c.zriver_control_v1_run_command(river_control, &command);
if (c.zriver_command_callback_v1_add_listener(
command_callback,
&command_callback_listener,
@ -75,15 +75,15 @@ fn handleGlobal(
interface: ?[*:0]const u8,
version: u32,
) callconv(.C) void {
// We only care about the river_window_manager global
// We only care about the river_control global
if (std.mem.eql(
u8,
std.mem.spanZ(interface.?),
std.mem.spanZ(@ptrCast([*:0]const u8, c.zriver_window_manager_v1_interface.name.?)),
std.mem.spanZ(@ptrCast([*:0]const u8, c.zriver_control_v1_interface.name.?)),
)) {
river_window_manager = @ptrCast(
*c.zriver_window_manager_v1,
c.wl_registry_bind(wl_registry, name, &c.zriver_window_manager_v1_interface, 1),
river_control_optional = @ptrCast(
*c.zriver_control_v1,
c.wl_registry_bind(wl_registry, name, &c.zriver_control_v1_interface, 1),
);
}
}