aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--build.zig2
-rw-r--r--protocol/river-status-unstable-v1.xml12
-rw-r--r--river/Config.zig20
-rw-r--r--river/InputManager.zig7
-rw-r--r--river/Mode.zig2
-rw-r--r--river/Seat.zig14
-rw-r--r--river/SeatStatus.zig4
-rw-r--r--river/StatusManager.zig2
-rw-r--r--river/command/declare_mode.zig11
-rw-r--r--river/command/enter_mode.zig2
10 files changed, 49 insertions, 27 deletions
diff --git a/build.zig b/build.zig
index 4d0017c..fb3a21e 100644
--- a/build.zig
+++ b/build.zig
@@ -112,7 +112,7 @@ pub fn build(b: *zbs.Builder) !void {
scanner.generate("zwp_pointer_constraints_v1", 1);
scanner.generate("zriver_control_v1", 1);
- scanner.generate("zriver_status_manager_v1", 2);
+ scanner.generate("zriver_status_manager_v1", 3);
scanner.generate("river_layout_manager_v3", 1);
scanner.generate("zwlr_layer_shell_v1", 4);
diff --git a/protocol/river-status-unstable-v1.xml b/protocol/river-status-unstable-v1.xml
index 13affaa..6a74256 100644
--- a/protocol/river-status-unstable-v1.xml
+++ b/protocol/river-status-unstable-v1.xml
@@ -16,7 +16,7 @@
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
</copyright>
- <interface name="zriver_status_manager_v1" version="2">
+ <interface name="zriver_status_manager_v1" version="3">
<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.
@@ -85,7 +85,7 @@
</event>
</interface>
- <interface name="zriver_seat_status_v1" version="1">
+ <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
@@ -121,5 +121,13 @@
</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>
diff --git a/river/Config.zig b/river/Config.zig
index 2da717c..9d0fa4c 100644
--- a/river/Config.zig
+++ b/river/Config.zig
@@ -57,7 +57,8 @@ border_color_unfocused: [4]f32 = [_]f32{ 0.34509804, 0.43137255, 0.45882353, 1.0
border_color_urgent: [4]f32 = [_]f32{ 0.86274510, 0.19607843, 0.18431373, 1.0 }, // Solarized red
/// Map of keymap mode name to mode id
-mode_to_id: std.StringHashMap(usize),
+/// Does not own the string keys. They are owned by the corresponding Mode struct.
+mode_to_id: std.StringHashMap(u32),
/// All user-defined keymap modes, indexed by mode id
modes: std.ArrayListUnmanaged(Mode),
@@ -98,7 +99,7 @@ cursor_hide_when_typing: HideCursorWhenTypingMode = .disabled,
pub fn init() !Self {
var self = Self{
- .mode_to_id = std.StringHashMap(usize).init(util.gpa),
+ .mode_to_id = std.StringHashMap(u32).init(util.gpa),
.modes = try std.ArrayListUnmanaged(Mode).initCapacity(util.gpa, 2),
};
errdefer self.deinit();
@@ -106,27 +107,22 @@ pub fn init() !Self {
// Start with two empty modes, "normal" and "locked"
{
// Normal mode, id 0
- const owned_slice = try util.gpa.dupe(u8, "normal");
+ const owned_slice = try util.gpa.dupeZ(u8, "normal");
try self.mode_to_id.putNoClobber(owned_slice, 0);
- self.modes.appendAssumeCapacity(.{});
+ self.modes.appendAssumeCapacity(.{ .name = owned_slice });
}
{
// Locked mode, id 1
- const owned_slice = try util.gpa.dupe(u8, "locked");
+ const owned_slice = try util.gpa.dupeZ(u8, "locked");
try self.mode_to_id.putNoClobber(owned_slice, 1);
- self.modes.appendAssumeCapacity(.{});
+ self.modes.appendAssumeCapacity(.{ .name = owned_slice });
}
return self;
}
pub fn deinit(self: *Self) void {
- {
- var it = self.mode_to_id.keyIterator();
- while (it.next()) |key| util.gpa.free(key.*);
- self.mode_to_id.deinit();
- }
-
+ self.mode_to_id.deinit();
for (self.modes.items) |*mode| mode.deinit();
self.modes.deinit(util.gpa);
diff --git a/river/InputManager.zig b/river/InputManager.zig
index cc159f3..3bcef06 100644
--- a/river/InputManager.zig
+++ b/river/InputManager.zig
@@ -188,7 +188,7 @@ fn handleInhibitActivate(
// Enter locked mode
seat_node.data.prev_mode_id = seat_node.data.mode_id;
- seat_node.data.mode_id = 1;
+ seat_node.data.enterMode(1);
}
self.exclusive_client = self.input_inhibit_manager.active_client;
@@ -215,8 +215,9 @@ fn handleInhibitDeactivate(
// have each Seat handle focus and enter their previous mode.
var seat_it = self.seats.first;
while (seat_it) |seat_node| : (seat_it = seat_node.next) {
- seat_node.data.focus(null);
- seat_node.data.mode_id = seat_node.data.prev_mode_id;
+ const seat = &seat_node.data;
+ seat.enterMode(seat.prev_mode_id);
+ seat.focus(null);
}
server.root.startTransaction();
diff --git a/river/Mode.zig b/river/Mode.zig
index 5793c50..cd0c1ab 100644
--- a/river/Mode.zig
+++ b/river/Mode.zig
@@ -23,11 +23,13 @@ const Mapping = @import("Mapping.zig");
const PointerMapping = @import("PointerMapping.zig");
const SwitchMapping = @import("SwitchMapping.zig");
+name: [:0]const u8,
mappings: std.ArrayListUnmanaged(Mapping) = .{},
pointer_mappings: std.ArrayListUnmanaged(PointerMapping) = .{},
switch_mappings: std.ArrayListUnmanaged(SwitchMapping) = .{},
pub fn deinit(self: *Self) void {
+ util.gpa.free(self.name);
for (self.mappings.items) |m| m.deinit();
self.mappings.deinit(util.gpa);
self.pointer_mappings.deinit(util.gpa);
diff --git a/river/Seat.zig b/river/Seat.zig
index 7fd16d3..9582313 100644
--- a/river/Seat.zig
+++ b/river/Seat.zig
@@ -63,10 +63,10 @@ keyboards: std.TailQueue(Keyboard) = .{},
switches: std.TailQueue(Switch) = .{},
/// ID of the current keymap mode
-mode_id: usize = 0,
+mode_id: u32 = 0,
/// ID of previous keymap mode, used when returning from "locked" mode
-prev_mode_id: usize = 0,
+prev_mode_id: u32 = 0,
/// Timer for repeating keyboard mappings
mapping_repeat_timer: *wl.EventSource,
@@ -358,6 +358,16 @@ pub fn handleViewUnmap(self: *Self, view: *View) void {
if (self.focused == .view and self.focused.view == view) self.focus(null);
}
+pub fn enterMode(self: *Self, mode_id: u32) void {
+ self.mode_id = mode_id;
+
+ var it = self.status_trackers.first;
+ while (it) |node| : (it = node.next) {
+ const seat_status = node.data.seat_status;
+ seat_status.sendMode(server.config.modes.items[mode_id].name);
+ }
+}
+
/// Is there a user-defined mapping for passed keycode, modifiers and keyboard state?
pub fn hasMapping(
self: *Self,
diff --git a/river/SeatStatus.zig b/river/SeatStatus.zig
index a4adf99..d06c7dd 100644
--- a/river/SeatStatus.zig
+++ b/river/SeatStatus.zig
@@ -21,6 +21,7 @@ const wayland = @import("wayland");
const wl = wayland.server.wl;
const zriver = wayland.server.zriver;
+const server = &@import("main.zig").server;
const util = @import("util.zig");
const Seat = @import("Seat.zig");
@@ -35,7 +36,8 @@ pub fn init(self: *Self, seat: *Seat, seat_status: *zriver.SeatStatusV1) void {
seat_status.setHandler(*Self, handleRequest, handleDestroy, self);
- // Send focused output/view once on bind
+ // Send all info once on bind
+ seat_status.sendMode(server.config.modes.items[seat.mode_id].name);
self.sendOutput(.focused);
self.sendFocusedView();
}
diff --git a/river/StatusManager.zig b/river/StatusManager.zig
index 1cf75eb..8239587 100644
--- a/river/StatusManager.zig
+++ b/river/StatusManager.zig
@@ -39,7 +39,7 @@ server_destroy: wl.Listener(*wl.Server) = wl.Listener(*wl.Server).init(handleSer
pub fn init(self: *Self) !void {
self.* = .{
- .global = try wl.Global.create(server.wl_server, zriver.StatusManagerV1, 2, ?*anyopaque, null, bind),
+ .global = try wl.Global.create(server.wl_server, zriver.StatusManagerV1, 3, ?*anyopaque, null, bind),
};
server.wl_server.addDestroyListener(&self.server_destroy);
diff --git a/river/command/declare_mode.zig b/river/command/declare_mode.zig
index 8b0d7a6..5b50b77 100644
--- a/river/command/declare_mode.zig
+++ b/river/command/declare_mode.zig
@@ -38,9 +38,12 @@ pub fn declareMode(
if (config.mode_to_id.get(new_mode_name) != null) return;
+ try config.mode_to_id.ensureUnusedCapacity(1);
try config.modes.ensureUnusedCapacity(util.gpa, 1);
- const owned_name = try util.gpa.dupe(u8, new_mode_name);
- errdefer util.gpa.free(owned_name);
- try config.mode_to_id.putNoClobber(owned_name, config.modes.items.len);
- config.modes.appendAssumeCapacity(.{});
+
+ const owned_name = try util.gpa.dupeZ(u8, new_mode_name);
+
+ const id = @intCast(u32, config.modes.items.len);
+ config.mode_to_id.putAssumeCapacityNoClobber(owned_name, id);
+ config.modes.appendAssumeCapacity(.{ .name = owned_name });
}
diff --git a/river/command/enter_mode.zig b/river/command/enter_mode.zig
index f5ae8e1..c982e60 100644
--- a/river/command/enter_mode.zig
+++ b/river/command/enter_mode.zig
@@ -59,5 +59,5 @@ pub fn enterMode(
return Error.Other;
}
- seat.mode_id = mode_id;
+ seat.enterMode(mode_id);
}