output: add output_title default option

Outputs now have a default option, "output_title". If this changes, the
outputs title is set to the option value. This title is currently only
relevant when run nested in a wayland/X11 session.

Co-authored-by: Isaac Freund <ifreund@ifreund.xyz>
This commit is contained in:
Leon Henrik Plickat 2021-02-01 14:16:55 +01:00 committed by Isaac Freund
parent 5e09b853f7
commit 7029a5cd3e
No known key found for this signature in database
GPG key ID: 86DED400DDFD7A11
5 changed files with 52 additions and 3 deletions

2
deps/zig-wlroots vendored

@ -1 +1 @@
Subproject commit 4db6b92146f22054b9a9363d0999cf3fb359a4fb
Subproject commit 5bc7fcf94e1d488a8e2316ff7ebdd0ca193d0309

View file

@ -280,7 +280,7 @@ A complete list may be found in _/usr/include/linux/input-event-codes.h_
and is made available through the _XCURSOR_THEME_ and _XCURSOR_SIZE_
environment variables.
# OPTIONS
## OPTIONS
River has various options that are saved in a typed key-value store. It also
allows users to store arbitrary custom options in the store. Options are
@ -299,6 +299,12 @@ name of the output as obtained from the xdg-output protocol.
*set-option* [-output _output_name_] _name_ _value_
Set the value of the specified option to _value_.
River declares certain default options for all outputs.
*output_title* (string)
Changing this option changes the title of the wayland and X11 backend
outputs.
# EXAMPLES
Bind bemenu-run to Super+P in normal mode:

View file

@ -45,6 +45,9 @@ output: ?*Output,
key: [*:0]const u8,
value: Value = .unset,
/// Emitted whenever the value of the option changes.
update: wl.Signal(*Self) = undefined,
handles: wl.list.Head(zriver.OptionHandleV1, null) = undefined,
pub fn create(options_manager: *OptionsManager, output: ?*Output, key: [*:0]const u8) !*Self {
@ -57,6 +60,7 @@ pub fn create(options_manager: *OptionsManager, output: ?*Output, key: [*:0]cons
.key = try util.gpa.dupeZ(u8, mem.span(key)),
};
self.handles.init();
self.update.init();
options_manager.options.append(self);
@ -101,6 +105,9 @@ pub fn set(self: *Self, value: Value) !void {
var it = self.handles.iterator(.forward);
while (it.next()) |handle| self.sendValue(handle);
// Call listeners, if any.
self.update.emit(self);
}
fn sendValue(self: Self, handle: *zriver.OptionHandleV1) void {

View file

@ -18,6 +18,8 @@
const Self = @This();
const std = @import("std");
const mem = std.mem;
const fmt = std.fmt;
const wlr = @import("wlroots");
const wayland = @import("wayland");
const wl = wayland.server.wl;
@ -35,6 +37,7 @@ const View = @import("View.zig");
const ViewStack = @import("view_stack.zig").ViewStack;
const AttachMode = @import("view_stack.zig").AttachMode;
const OutputStatus = @import("OutputStatus.zig");
const Option = @import("Option.zig");
const State = struct {
/// A bit field of focused tags
@ -84,6 +87,9 @@ enable: wl.Listener(*wlr.Output) = wl.Listener(*wlr.Output).init(handleEnable),
frame: wl.Listener(*wlr.Output) = wl.Listener(*wlr.Output).init(handleFrame),
mode: wl.Listener(*wlr.Output) = wl.Listener(*wlr.Output).init(handleMode),
// Listeners for options
output_title: wl.Listener(*Option) = wl.Listener(*Option).init(handleTitleChange),
pub fn init(self: *Self, root: *Root, wlr_output: *wlr.Output) !void {
// Some backends don't have modes. DRM+KMS does, and we need to set a mode
// before we can use the output. The mode is a tuple of (width, height,
@ -138,6 +144,10 @@ pub fn init(self: *Self, root: *Root, wlr_output: *wlr.Output) !void {
.height = effective_resolution.height,
};
}
var buf: ["river - ".len + wlr_output.name.len + 1]u8 = undefined;
const default_title = fmt.bufPrintZ(&buf, "river - {}", .{mem.spanZ(&wlr_output.name)}) catch unreachable;
try self.defaultOption("output_title", .{ .string = default_title.ptr }, &self.output_title);
}
pub fn getLayer(self: *Self, layer: zwlr.LayerShellV1.Layer) *std.TailQueue(LayerSurface) {
@ -545,3 +555,29 @@ pub fn getEffectiveResolution(self: *Self) struct { width: u32, height: u32 } {
.height = @intCast(u32, height),
};
}
pub fn setTitle(self: *Self, title: [*:0]const u8) void {
if (self.wlr_output.isWl()) {
self.wlr_output.wlSetTitle(title);
} else if (self.wlr_output.isX11()) {
self.wlr_output.x11SetTitle(title);
}
}
/// Create an option for this output, attach a listener which is called when
/// the option changed and initialize with a default value. Note that the
/// listener is called once through this function.
fn defaultOption(
self: *Self,
key: [*:0]const u8,
value: Option.Value,
listener: *wl.Listener(*Option),
) !void {
const option = try Option.create(&self.root.server.options_manager, self, key);
option.update.add(listener);
try option.set(value);
}
fn handleTitleChange(listener: *wl.Listener(*Option), option: *Option) void {
if (option.value.string) |title| option.output.?.setTitle(title);
}

View file

@ -112,12 +112,12 @@ pub fn init(self: *Self) !void {
self.config = try Config.init();
try self.decoration_manager.init(self);
try self.options_manager.init(self);
try self.root.init(self);
// Must be called after root is initialized
try self.input_manager.init(self);
try self.control.init(self);
try self.status_manager.init(self);
try self.options_manager.init(self);
// These all free themselves when the wl_server is destroyed
_ = try wlr.DataDeviceManager.create(self.wl_server);