keyboard-groups: use globber for identifier matching
This commit is contained in:
		
				
					committed by
					
						 Isaac Freund
						Isaac Freund
					
				
			
			
				
	
			
			
			
						parent
						
							540ca043df
						
					
				
				
					commit
					dd9933b6a1
				
			| @ -442,7 +442,8 @@ matches everything while _\*\*_ and the empty string are invalid. | ||||
| *keyboard-group-add* _group_name_ _input_device_name_ | ||||
| 	Add a keyboard to a keyboard group, identified by the keyboard's | ||||
| 	input device name. Any currently connected and future keyboards with | ||||
| 	the given name will be added to the group. | ||||
| 	the given name will be added to the group. Simple globbing patterns are | ||||
| 	supported, see the rules section for further information on globs. | ||||
|  | ||||
| *keyboard-group-remove* _group_name_ _input_device_name_ | ||||
| 	Remove a keyboard from a keyboard group, identified by the keyboard's | ||||
|  | ||||
| @ -21,6 +21,7 @@ const assert = std.debug.assert; | ||||
| const wlr = @import("wlroots"); | ||||
| const wl = @import("wayland").server.wl; | ||||
| const xkb = @import("xkbcommon"); | ||||
| const globber = @import("globber"); | ||||
|  | ||||
| const server = &@import("main.zig").server; | ||||
| const util = @import("util.zig"); | ||||
| @ -52,13 +53,15 @@ pub fn init(self: *Self, seat: *Seat, wlr_device: *wlr.InputDevice) !void { | ||||
|     // wlroots will log a more detailed error if this fails. | ||||
|     if (!wlr_keyboard.setKeymap(server.config.keymap)) return error.OutOfMemory; | ||||
|  | ||||
|     // Add to keyboard group, if applicable. | ||||
|     var it = seat.keyboard_groups.first; | ||||
|     while (it) |node| : (it = node.next) { | ||||
|         if (node.data.identifiers.contains(self.device.identifier)) { | ||||
|             // wlroots will log an error if this fails explaining the reason. | ||||
|             _ = node.data.wlr_group.addKeyboard(wlr_keyboard); | ||||
|             break; | ||||
|     // Add to keyboard-group, if applicable. | ||||
|     var group_it = seat.keyboard_groups.first; | ||||
|     outer: while (group_it) |group_node| : (group_it = group_node.next) { | ||||
|         for (group_node.data.globs.items) |glob| { | ||||
|             if (globber.match(glob, self.device.identifier)) { | ||||
|                 // wlroots will log an error if this fails explaining the reason. | ||||
|                 _ = group_node.data.wlr_group.addKeyboard(wlr_keyboard); | ||||
|                 break :outer; | ||||
|             } | ||||
|         } | ||||
|     } | ||||
|  | ||||
|  | ||||
| @ -20,6 +20,7 @@ const std = @import("std"); | ||||
| const assert = std.debug.assert; | ||||
| const mem = std.mem; | ||||
|  | ||||
| const globber = @import("globber"); | ||||
| const wlr = @import("wlroots"); | ||||
| const wl = @import("wayland").server.wl; | ||||
| const xkb = @import("xkbcommon"); | ||||
| @ -35,7 +36,7 @@ const Keyboard = @import("Keyboard.zig"); | ||||
| seat: *Seat, | ||||
| wlr_group: *wlr.KeyboardGroup, | ||||
| name: []const u8, | ||||
| identifiers: std.StringHashMapUnmanaged(void) = .{}, | ||||
| globs: std.ArrayListUnmanaged([]const u8) = .{}, | ||||
|  | ||||
| pub fn create(seat: *Seat, name: []const u8) !void { | ||||
|     log.debug("new keyboard group: '{s}'", .{name}); | ||||
| @ -63,11 +64,11 @@ pub fn destroy(group: *KeyboardGroup) void { | ||||
|     log.debug("destroying keyboard group: '{s}'", .{group.name}); | ||||
|  | ||||
|     util.gpa.free(group.name); | ||||
|     { | ||||
|         var it = group.identifiers.keyIterator(); | ||||
|         while (it.next()) |id| util.gpa.free(id.*); | ||||
|  | ||||
|     for (group.globs.items) |glob| { | ||||
|         util.gpa.free(glob); | ||||
|     } | ||||
|     group.identifiers.deinit(util.gpa); | ||||
|     group.globs.deinit(util.gpa); | ||||
|  | ||||
|     group.wlr_group.destroy(); | ||||
|  | ||||
| @ -77,14 +78,23 @@ pub fn destroy(group: *KeyboardGroup) void { | ||||
| } | ||||
|  | ||||
| pub fn addIdentifier(group: *KeyboardGroup, new_id: []const u8) !void { | ||||
|     if (group.identifiers.contains(new_id)) return; | ||||
|     for (group.globs.items) |glob| { | ||||
|         if (mem.eql(u8, glob, new_id)) return; | ||||
|     } | ||||
|  | ||||
|     log.debug("keyboard group '{s}' adding identifier: '{s}'", .{ group.name, new_id }); | ||||
|  | ||||
|     const owned_id = try util.gpa.dupe(u8, new_id); | ||||
|     errdefer util.gpa.free(owned_id); | ||||
|  | ||||
|     try group.identifiers.put(util.gpa, owned_id, {}); | ||||
|     // Glob is validated in the command handler. | ||||
|     try group.globs.append(util.gpa, owned_id); | ||||
|     errdefer { | ||||
|         // Not used now, but if at any point this function is modified to that | ||||
|         // it may return an error after the glob pattern is added to the list, | ||||
|         // the list will have a pointer to freed memory in its last position. | ||||
|         _ = group.globs.pop(); | ||||
|     } | ||||
|  | ||||
|     // Add any existing matching keyboards to the group. | ||||
|     var it = server.input_manager.devices.iterator(.forward); | ||||
| @ -92,7 +102,7 @@ pub fn addIdentifier(group: *KeyboardGroup, new_id: []const u8) !void { | ||||
|         if (device.seat != group.seat) continue; | ||||
|         if (device.wlr_device.type != .keyboard) continue; | ||||
|  | ||||
|         if (mem.eql(u8, new_id, device.identifier)) { | ||||
|         if (globber.match(device.identifier, new_id)) { | ||||
|             log.debug("found existing matching keyboard; adding to group", .{}); | ||||
|  | ||||
|             if (!group.wlr_group.addKeyboard(device.wlr_device.toKeyboard())) { | ||||
| @ -108,8 +118,13 @@ pub fn addIdentifier(group: *KeyboardGroup, new_id: []const u8) !void { | ||||
| } | ||||
|  | ||||
| pub fn removeIdentifier(group: *KeyboardGroup, id: []const u8) !void { | ||||
|     if (group.identifiers.fetchRemove(id)) |kv| { | ||||
|         util.gpa.free(kv.key); | ||||
|     for (group.globs.items, 0..) |glob, index| { | ||||
|         if (mem.eql(u8, glob, id)) { | ||||
|             _ = group.globs.orderedRemove(index); | ||||
|             break; | ||||
|         } | ||||
|     } else { | ||||
|         return; | ||||
|     } | ||||
|  | ||||
|     var it = server.input_manager.devices.iterator(.forward); | ||||
| @ -117,7 +132,7 @@ pub fn removeIdentifier(group: *KeyboardGroup, id: []const u8) !void { | ||||
|         if (device.seat != group.seat) continue; | ||||
|         if (device.wlr_device.type != .keyboard) continue; | ||||
|  | ||||
|         if (mem.eql(u8, device.identifier, id)) { | ||||
|         if (globber.match(device.identifier, id)) { | ||||
|             const wlr_keyboard = device.wlr_device.toKeyboard(); | ||||
|             assert(wlr_keyboard.group == group.wlr_group); | ||||
|             group.wlr_group.removeKeyboard(wlr_keyboard); | ||||
|  | ||||
| @ -17,6 +17,8 @@ | ||||
| const std = @import("std"); | ||||
| const mem = std.mem; | ||||
|  | ||||
| const globber = @import("globber"); | ||||
|  | ||||
| const server = &@import("../main.zig").server; | ||||
| const util = @import("../util.zig"); | ||||
|  | ||||
| @ -69,6 +71,7 @@ pub fn keyboardGroupAdd( | ||||
|         out.* = msg; | ||||
|         return; | ||||
|     }; | ||||
|     try globber.validate(args[2]); | ||||
|     try group.addIdentifier(args[2]); | ||||
| } | ||||
|  | ||||
|  | ||||
		Reference in New Issue
	
	Block a user