From 03a2da9690357b06bdf75cbe8ed1e126d964b548 Mon Sep 17 00:00:00 2001 From: Leon Henrik Plickat Date: Mon, 19 Oct 2020 12:39:52 +0200 Subject: [PATCH] Introduce mode "locked" This mode is automatically entered when the screen is locked. --- doc/riverctl.1.scd | 4 ++-- river/Config.zig | 19 +++++++++++++++---- river/InputManager.zig | 9 +++++++-- river/Seat.zig | 3 +++ river/command/enter_mode.zig | 22 +++++++++++++++++++++- 5 files changed, 48 insertions(+), 9 deletions(-) diff --git a/doc/riverctl.1.scd b/doc/riverctl.1.scd index 8ede532..9a73a88 100644 --- a/doc/riverctl.1.scd +++ b/doc/riverctl.1.scd @@ -135,8 +135,8 @@ that tag 1 through 9 are visible. When set to _strict_ this is not the case. The focus will be updated on every cursor movement. *map* [-release] _mode_ _modifiers_ _key_ _command_ - _mode_ is either “normal” (the default mode) or a mode created with - *declare-mode*. + _mode_ is either "normal" (the default mode), "locked" (the mode entered when + an input inhibitor such as a lock screen is active) or a mode created with *declare-mode*. If _-release_ is specified the mapping is executed on key release rather than key press. _modifiers_ is a list of one or more of the following modifiers separated with a plus sign: diff --git a/river/Config.zig b/river/Config.zig index 04b1893..f1ed500 100644 --- a/river/Config.zig +++ b/river/Config.zig @@ -89,11 +89,22 @@ pub fn init() !Self { .csd_filter = std.ArrayList([]const u8).init(util.gpa), }; - // Start with a single, empty mode called normal errdefer self.deinit(); - const owned_slice = try std.mem.dupe(util.gpa, u8, "normal"); - try self.mode_to_id.putNoClobber(owned_slice, 0); - try self.modes.append(Mode.init()); + + // Start with two empty modes, "normal" and "locked" + try self.modes.ensureCapacity(2); + { + // Normal mode, id 0 + const owned_slice = try std.mem.dupe(util.gpa, u8, "normal"); + try self.mode_to_id.putNoClobber(owned_slice, 0); + self.modes.appendAssumeCapacity(Mode.init()); + } + { + // Locked mode, id 1 + const owned_slice = try std.mem.dupe(util.gpa, u8, "locked"); + try self.mode_to_id.putNoClobber(owned_slice, 1); + self.modes.appendAssumeCapacity(Mode.init()); + } return self; } diff --git a/river/InputManager.zig b/river/InputManager.zig index 55de3b2..d618c52 100644 --- a/river/InputManager.zig +++ b/river/InputManager.zig @@ -110,10 +110,14 @@ fn handleInhibitActivate(listener: ?*c.wl_listener, data: ?*c_void) callconv(.C) log.debug(.input_manager, "input inhibitor activated", .{}); - // Clear focus of all seats var seat_it = self.seats.first; while (seat_it) |seat_node| : (seat_it = seat_node.next) { + // Clear focus of all seats seat_node.data.setFocusRaw(.{ .none = {} }); + + // Enter locked mode + seat_node.data.prev_mode_id = seat_node.data.mode_id; + seat_node.data.mode_id = 1; } self.exclusive_client = self.wlr_input_inhibit_manager.active_client; @@ -134,10 +138,11 @@ fn handleInhibitDeactivate(listener: ?*c.wl_listener, data: ?*c_void) callconv(. } // After ensuring that any possible layer surface focus grab has occured, - // have each Seat handle focus. + // 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; } self.server.root.startTransaction(); diff --git a/river/Seat.zig b/river/Seat.zig index 638954d..c35ab79 100644 --- a/river/Seat.zig +++ b/river/Seat.zig @@ -53,6 +53,9 @@ keyboards: std.TailQueue(Keyboard) = .{}, /// ID of the current keymap mode mode_id: usize = 0, +/// ID of previous keymap mode, used when returning from "locked" mode +prev_mode_id: usize = 0, + /// Currently focused output, may be the noop output if no focused_output: *Output, diff --git a/river/command/enter_mode.zig b/river/command/enter_mode.zig index c60dcf9..ada18e8 100644 --- a/river/command/enter_mode.zig +++ b/river/command/enter_mode.zig @@ -30,9 +30,18 @@ pub fn enterMode( if (args.len < 2) return Error.NotEnoughArguments; if (args.len > 2) return Error.TooManyArguments; + if (seat.mode_id == 1) { + out.* = try std.fmt.allocPrint( + allocator, + "manually exiting mode 'locked' is not allowed", + .{}, + ); + return Error.Other; + } + const config = seat.input_manager.server.config; const target_mode = args[1]; - seat.mode_id = config.mode_to_id.get(target_mode) orelse { + const mode_id = config.mode_to_id.get(target_mode) orelse { out.* = try std.fmt.allocPrint( allocator, "cannot enter non-existant mode '{}'", @@ -40,4 +49,15 @@ pub fn enterMode( ); return Error.Other; }; + + if (mode_id == 1) { + out.* = try std.fmt.allocPrint( + allocator, + "manually entering mode 'locked' is not allowed", + .{}, + ); + return Error.Other; + } + + seat.mode_id = mode_id; }