Implement map -release
This commit is contained in:
parent
7e02fb679c
commit
52cd871151
5 changed files with 76 additions and 32 deletions
|
@ -123,9 +123,11 @@ that tag 1 through 9 are visible.
|
||||||
but let the currently focused window in focus.
|
but let the currently focused window in focus.
|
||||||
When set to _strict_ this is not the case. The focus will be updated on every cursor movement.
|
When set to _strict_ this is not the case. The focus will be updated on every cursor movement.
|
||||||
|
|
||||||
*map* _mode_ _modifiers_ _key_ _command_
|
*map* [-release] _mode_ _modifiers_ _key_ _command_
|
||||||
_mode_ is either “normal” (the default mode) or a mode created with
|
_mode_ is either “normal” (the default mode) or a mode created with
|
||||||
*declare-mode*. _modifiers_ is a list of one or more of the following
|
*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:
|
modifiers separated with a plus sign:
|
||||||
|
|
||||||
- Shift
|
- Shift
|
||||||
|
|
|
@ -103,13 +103,15 @@ fn handleKey(listener: ?*c.wl_listener, data: ?*c_void) callconv(.C) void {
|
||||||
var handled = false;
|
var handled = false;
|
||||||
// TODO: These modifiers aren't properly handled, see sway's code
|
// TODO: These modifiers aren't properly handled, see sway's code
|
||||||
const modifiers = c.wlr_keyboard_get_modifiers(wlr_keyboard);
|
const modifiers = c.wlr_keyboard_get_modifiers(wlr_keyboard);
|
||||||
if (event.state == .WLR_KEY_PRESSED) {
|
const released = event.state == .WLR_KEY_RELEASED;
|
||||||
|
|
||||||
var i: usize = 0;
|
var i: usize = 0;
|
||||||
while (i < translated_keysyms_len) : (i += 1) {
|
while (i < translated_keysyms_len) : (i += 1) {
|
||||||
if (self.handleBuiltinMapping(translated_keysyms.?[i])) {
|
// Handle builtin mapping only when keys are pressed
|
||||||
|
if (!released and self.handleBuiltinMapping(translated_keysyms.?[i])) {
|
||||||
handled = true;
|
handled = true;
|
||||||
break;
|
break;
|
||||||
} else if (self.seat.handleMapping(translated_keysyms.?[i], modifiers)) {
|
} else if (self.seat.handleMapping(translated_keysyms.?[i], modifiers, released)) {
|
||||||
handled = true;
|
handled = true;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -117,16 +119,16 @@ fn handleKey(listener: ?*c.wl_listener, data: ?*c_void) callconv(.C) void {
|
||||||
if (!handled) {
|
if (!handled) {
|
||||||
i = 0;
|
i = 0;
|
||||||
while (i < raw_keysyms_len) : (i += 1) {
|
while (i < raw_keysyms_len) : (i += 1) {
|
||||||
if (self.handleBuiltinMapping(raw_keysyms.?[i])) {
|
// Handle builtin mapping only when keys are pressed
|
||||||
|
if (!released and self.handleBuiltinMapping(raw_keysyms.?[i])) {
|
||||||
handled = true;
|
handled = true;
|
||||||
break;
|
break;
|
||||||
} else if (self.seat.handleMapping(raw_keysyms.?[i], modifiers)) {
|
} else if (self.seat.handleMapping(raw_keysyms.?[i], modifiers, released)) {
|
||||||
handled = true;
|
handled = true;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
if (!handled) {
|
if (!handled) {
|
||||||
// Otherwise, we pass it along to the client.
|
// Otherwise, we pass it along to the client.
|
||||||
|
|
|
@ -25,10 +25,14 @@ keysym: c.xkb_keysym_t,
|
||||||
modifiers: u32,
|
modifiers: u32,
|
||||||
command_args: []const []const u8,
|
command_args: []const []const u8,
|
||||||
|
|
||||||
|
/// When set to true the mapping will be executed on key release rather than on press
|
||||||
|
release: bool,
|
||||||
|
|
||||||
pub fn init(
|
pub fn init(
|
||||||
allocator: *std.mem.Allocator,
|
allocator: *std.mem.Allocator,
|
||||||
keysym: c.xkb_keysym_t,
|
keysym: c.xkb_keysym_t,
|
||||||
modifiers: u32,
|
modifiers: u32,
|
||||||
|
release: bool,
|
||||||
command_args: []const []const u8,
|
command_args: []const []const u8,
|
||||||
) !Self {
|
) !Self {
|
||||||
const owned_args = try allocator.alloc([]u8, command_args.len);
|
const owned_args = try allocator.alloc([]u8, command_args.len);
|
||||||
|
@ -40,6 +44,7 @@ pub fn init(
|
||||||
return Self{
|
return Self{
|
||||||
.keysym = keysym,
|
.keysym = keysym,
|
||||||
.modifiers = modifiers,
|
.modifiers = modifiers,
|
||||||
|
.release = release,
|
||||||
.command_args = owned_args,
|
.command_args = owned_args,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
|
@ -262,10 +262,10 @@ pub fn handleViewUnmap(self: *Self, view: *View) void {
|
||||||
|
|
||||||
/// Handle any user-defined mapping for the passed keysym and modifiers
|
/// Handle any user-defined mapping for the passed keysym and modifiers
|
||||||
/// Returns true if the key was handled
|
/// Returns true if the key was handled
|
||||||
pub fn handleMapping(self: *Self, keysym: c.xkb_keysym_t, modifiers: u32) bool {
|
pub fn handleMapping(self: *Self, keysym: c.xkb_keysym_t, modifiers: u32, released: bool) bool {
|
||||||
const modes = &self.input_manager.server.config.modes;
|
const modes = &self.input_manager.server.config.modes;
|
||||||
for (modes.items[self.mode_id].mappings.items) |mapping| {
|
for (modes.items[self.mode_id].mappings.items) |mapping| {
|
||||||
if (modifiers == mapping.modifiers and keysym == mapping.keysym) {
|
if (modifiers == mapping.modifiers and keysym == mapping.keysym and released == mapping.release) {
|
||||||
// Execute the bound command
|
// Execute the bound command
|
||||||
const args = mapping.command_args;
|
const args = mapping.command_args;
|
||||||
var out: ?[]const u8 = null;
|
var out: ?[]const u8 = null;
|
||||||
|
|
|
@ -50,20 +50,23 @@ pub fn map(
|
||||||
args: []const []const u8,
|
args: []const []const u8,
|
||||||
out: *?[]const u8,
|
out: *?[]const u8,
|
||||||
) Error!void {
|
) Error!void {
|
||||||
if (args.len < 5) return Error.NotEnoughArguments;
|
const optionals = parseOptionalArgs(args[1..]);
|
||||||
|
// offset caused by optional arguments
|
||||||
|
const offset = optionals.i;
|
||||||
|
if (args.len - offset < 5) return Error.NotEnoughArguments;
|
||||||
|
|
||||||
const mode_id = try modeNameToId(allocator, seat, args[1], out);
|
const mode_id = try modeNameToId(allocator, seat, args[1 + offset], out);
|
||||||
const modifiers = try parseModifiers(allocator, args[2], out);
|
const modifiers = try parseModifiers(allocator, args[2 + offset], out);
|
||||||
|
|
||||||
// Parse the keysym
|
// Parse the keysym
|
||||||
const keysym_name = try std.cstr.addNullByte(allocator, args[3]);
|
const keysym_name = try std.cstr.addNullByte(allocator, args[3 + offset]);
|
||||||
defer allocator.free(keysym_name);
|
defer allocator.free(keysym_name);
|
||||||
const keysym = c.xkb_keysym_from_name(keysym_name, .XKB_KEYSYM_CASE_INSENSITIVE);
|
const keysym = c.xkb_keysym_from_name(keysym_name, .XKB_KEYSYM_CASE_INSENSITIVE);
|
||||||
if (keysym == c.XKB_KEY_NoSymbol) {
|
if (keysym == c.XKB_KEY_NoSymbol) {
|
||||||
out.* = try std.fmt.allocPrint(
|
out.* = try std.fmt.allocPrint(
|
||||||
allocator,
|
allocator,
|
||||||
"invalid keysym '{}'",
|
"invalid keysym '{}'",
|
||||||
.{args[3]},
|
.{args[3 + offset]},
|
||||||
);
|
);
|
||||||
return Error.Other;
|
return Error.Other;
|
||||||
}
|
}
|
||||||
|
@ -71,17 +74,17 @@ pub fn map(
|
||||||
// Check if the mapping already exists
|
// Check if the mapping already exists
|
||||||
const mode_mappings = &seat.input_manager.server.config.modes.items[mode_id].mappings;
|
const mode_mappings = &seat.input_manager.server.config.modes.items[mode_id].mappings;
|
||||||
for (mode_mappings.items) |existant_mapping| {
|
for (mode_mappings.items) |existant_mapping| {
|
||||||
if (existant_mapping.modifiers == modifiers and existant_mapping.keysym == keysym) {
|
if (existant_mapping.modifiers == modifiers and existant_mapping.keysym == keysym and existant_mapping.release == optionals.release) {
|
||||||
out.* = try std.fmt.allocPrint(
|
out.* = try std.fmt.allocPrint(
|
||||||
allocator,
|
allocator,
|
||||||
"a mapping for modifiers '{}' and keysym '{}' already exists",
|
"a mapping for modifiers '{}' and keysym '{}' already exists",
|
||||||
.{ args[2], args[3] },
|
.{ args[2 + offset], args[3 + offset] },
|
||||||
);
|
);
|
||||||
return Error.Other;
|
return Error.Other;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
try mode_mappings.append(try Mapping.init(util.gpa, keysym, modifiers, args[4..]));
|
try mode_mappings.append(try Mapping.init(util.gpa, keysym, modifiers, optionals.release, args[4 + offset ..]));
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Create a new pointer mapping for a given mode
|
/// Create a new pointer mapping for a given mode
|
||||||
|
@ -176,3 +179,35 @@ fn parseModifiers(allocator: *std.mem.Allocator, modifiers_str: []const u8, out:
|
||||||
}
|
}
|
||||||
return modifiers;
|
return modifiers;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const OptionalArgsContainer = struct {
|
||||||
|
i: usize,
|
||||||
|
release: bool,
|
||||||
|
};
|
||||||
|
|
||||||
|
/// Parses optional args (such as -release) and return the index of the first argument that is
|
||||||
|
/// not an optional argument
|
||||||
|
/// Returns an OptionalArgsContainer with the settings set according to the args
|
||||||
|
/// Errors cant occur because it returns as soon as it gets an unknown argument
|
||||||
|
fn parseOptionalArgs(args: []const []const u8) OptionalArgsContainer {
|
||||||
|
// Set to defaults
|
||||||
|
var parsed = OptionalArgsContainer{
|
||||||
|
// i is the number of arguments consumed
|
||||||
|
.i = 0,
|
||||||
|
.release = false,
|
||||||
|
};
|
||||||
|
|
||||||
|
var i: usize = 0;
|
||||||
|
for (args) |arg| {
|
||||||
|
if (std.mem.eql(u8, arg, "-release")) {
|
||||||
|
parsed.release = true;
|
||||||
|
i += 1;
|
||||||
|
} else {
|
||||||
|
// Break if the arg is not an option
|
||||||
|
parsed.i = i;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return parsed;
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in a new issue