river-options: rework, bump to v2

Options are now all global but may be overridden per-output. If an
output local value is requested but none has been set, the global value
is provided instead. This makes for much better ergonomics when
configuring layout related options in particular.
This commit is contained in:
Isaac Freund
2021-04-15 00:28:39 +02:00
parent 33fb7725c5
commit d08032d685
19 changed files with 919 additions and 734 deletions

View File

@ -1,11 +1,12 @@
#!/bin/sh
# This is the example configuration file for river(1).
# This is the example configuration file for river.
#
# If you wish to edit this, you will probably want to copy it to
# $XDG_CONFIG_HOME/river/init or $HOME/.config/river/init first.
#
# See the riverctl(1) man page for complete documentation
# See the river(1), riverctl(1), and river(1) man pages for complete
# documentation.
# Use the "logo" key as the primary modifier
mod="Mod4"
@ -39,6 +40,16 @@ riverctl map normal $mod+Shift Comma send-to-output previous
# Mod+Return to bump the focused view to the top of the layout stack
riverctl map normal $mod Return zoom
# Mod+H and Mod+L to decrease/increase the main_factor option by 0.05
# rivertile(1) uses this option to determine the width of the main stack.
riverctl map normal $mod H spawn riverctl mod-option -focused-output main_factor -0.05
riverctl map normal $mod L spawn riverctl mod-option -focused-output main_factor +0.05
# Mod+Shift+H and Mod+Shift+L to increment/decrement the main_count option.
# rivertile(1) uses this option to determine the number of "main" views in the layout.
riverctl map normal $mod+Shift H spawn riverctl mod-option -focused-output main_count +1
riverctl map normal $mod+Shift L spawn riverctl mod-option -focused-output main_count -1
# Mod+Alt+{H,J,K,L} to move views
riverctl map normal $mod+Mod1 H move left 100
riverctl map normal $mod+Mod1 J move down 100
@ -93,10 +104,10 @@ riverctl map normal $mod Space toggle-float
riverctl map normal $mod F toggle-fullscreen
# Mod+{Up,Right,Down,Left} to change layout orientation
riverctl map normal $mod Up spawn riverctl set-option -focused-output layout tile-up
riverctl map normal $mod Right spawn riverctl set-option -focused-output layout tile-right
riverctl map normal $mod Down spawn riverctl set-option -focused-output layout tile-down
riverctl map normal $mod Left spawn riverctl set-option -focused-output layout tile-left
riverctl map normal $mod Up spawn riverctl set-option -focused-output main_location top
riverctl map normal $mod Right spawn riverctl set-option -focused-output main_location right
riverctl map normal $mod Down spawn riverctl set-option -focused-output main_location bottom
riverctl map normal $mod Left spawn riverctl set-option -focused-output main_location left
# Declare a passthrough mode. This mode has only a single mapping to return to
# normal mode. This makes it useful for testing a nested wayland compositor
@ -134,18 +145,6 @@ done
# Set repeat rate
riverctl set-repeat 50 300
# Set the layout on startup
riverctl spawn rivertile
riverctl set-option -focused-output layout tile-left
# Mod+Alt+{1..9} to set main amount
# Mod+Alt+Ctrl+{1..9} to set main factor
#for i in $(seq 1 9)
#do
# riverctl map normal $mod+mod1 spawn riverctl set-option -focused-output main_amount "${i}"
# riverctl map normal $mod+Control+mod1 spawn riverctl set-option -focused-output main_factor "0.${i}"
#done
# Set app-ids of views which should float
riverctl float-filter-add "float"
riverctl float-filter-add "popup"
@ -155,3 +154,8 @@ riverctl csd-filter-add "gedit"
# Set opacity and fade effect
# riverctl opacity 1.0 0.75 0.0 0.1 20
# Exec into the default layout generator, rivertile.
# River will send the process group of the init executable SIGTERM on exit.
riverctl set-option layout rivertile
exec rivertile

View File

@ -1,102 +0,0 @@
// This file is part of river, a dynamic tiling wayland compositor.
//
// Copyright 2020 The River Developers
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <https://www.gnu.org/licenses/>.
const std = @import("std");
const os = std.os;
const mem = std.mem;
const fmt = std.fmt;
const wayland = @import("wayland");
const wl = wayland.client.wl;
const zriver = wayland.client.zriver;
const SetupContext = struct {
options_manager: ?*zriver.OptionsManagerV1 = null,
outputs: std.ArrayList(*wl.Output) = std.ArrayList(*wl.Output).init(std.heap.c_allocator),
};
const ValueType = enum {
int,
uint,
fixed,
string,
};
/// Disclaimer, the output handling implemented here is by no means robust. A
/// proper client should likely use xdg-output to identify outputs by name.
///
/// Usage: ./options <key> output_num|NULL [<value_type> <value>]
/// Examples:
/// ./options foo
/// ./options foo NULL uint 42
/// ./options foo 1 string ziggy
pub fn main() !void {
const display = try wl.Display.connect(null);
const registry = try display.getRegistry();
var context = SetupContext{};
registry.setListener(*SetupContext, registryListener, &context) catch unreachable;
_ = try display.roundtrip();
const options_manager = context.options_manager orelse return error.RiverOptionsManagerNotAdvertised;
const key = os.argv[1];
const output = if (mem.eql(u8, "NULL", mem.span(os.argv[2])))
null
else
context.outputs.items[fmt.parseInt(u32, mem.span(os.argv[2]), 10) catch return error.InvalidOutput];
const handle = try options_manager.getOptionHandle(key, output);
handle.setListener([*:0]u8, optionListener, key) catch unreachable;
if (os.argv.len > 3) {
const value_type = std.meta.stringToEnum(ValueType, mem.span(os.argv[3])) orelse return error.InvalidType;
switch (value_type) {
.int => handle.setIntValue(fmt.parseInt(i32, mem.span(os.argv[4]), 10) catch return error.InvalidInt),
.uint => handle.setUintValue(fmt.parseInt(u32, mem.span(os.argv[4]), 10) catch return error.InvalidUint),
.fixed => handle.setFixedValue(wl.Fixed.fromDouble(fmt.parseFloat(f64, mem.span(os.argv[4])) catch return error.InvalidFixed)),
.string => handle.setStringValue(os.argv[4]),
}
}
// Loop forever, listening for new events.
while (true) _ = try display.dispatch();
}
fn registryListener(registry: *wl.Registry, event: wl.Registry.Event, context: *SetupContext) void {
switch (event) {
.global => |global| {
if (std.cstr.cmp(global.interface, zriver.OptionsManagerV1.getInterface().name) == 0) {
context.options_manager = registry.bind(global.name, zriver.OptionsManagerV1, 1) catch return;
} else if (std.cstr.cmp(global.interface, wl.Output.getInterface().name) == 0) {
const output = registry.bind(global.name, wl.Output, 1) catch return;
context.outputs.append(output) catch @panic("out of memory");
}
},
.global_remove => {},
}
}
fn optionListener(handle: *zriver.OptionHandleV1, event: zriver.OptionHandleV1.Event, key: [*:0]const u8) void {
switch (event) {
.unset => std.debug.print("option '{}' unset\n", .{key}),
.int_value => |ev| std.debug.print("option '{}' of type int has value {}\n", .{ key, ev.value }),
.uint_value => |ev| std.debug.print("option '{}' of type uint has value {}\n", .{ key, ev.value }),
.fixed_value => |ev| std.debug.print("option '{}' of type fixed has value {}\n", .{ key, ev.value.toDouble() }),
.string_value => |ev| std.debug.print("option '{}' of type string has value {}\n", .{ key, ev.value }),
}
}