| 1 |
const std = @import("std");
|
| 2 |
const testing = std.testing;
|
| 3 |
|
| 4 |
const Mod4Mask: u32 = 1 << 6;
|
| 5 |
const Mod1Mask: u32 = 1 << 3;
|
| 6 |
const ShiftMask: u32 = 1 << 0;
|
| 7 |
const ControlMask: u32 = 1 << 2;
|
| 8 |
|
| 9 |
fn parse_modifier(name: []const u8) u32 {
|
| 10 |
if (std.mem.eql(u8, name, "Mod4") or std.mem.eql(u8, name, "mod4") or std.mem.eql(u8, name, "super")) {
|
| 11 |
return Mod4Mask;
|
| 12 |
} else if (std.mem.eql(u8, name, "Mod1") or std.mem.eql(u8, name, "mod1") or std.mem.eql(u8, name, "alt")) {
|
| 13 |
return Mod1Mask;
|
| 14 |
} else if (std.mem.eql(u8, name, "Shift") or std.mem.eql(u8, name, "shift")) {
|
| 15 |
return ShiftMask;
|
| 16 |
} else if (std.mem.eql(u8, name, "Control") or std.mem.eql(u8, name, "control") or std.mem.eql(u8, name, "ctrl")) {
|
| 17 |
return ControlMask;
|
| 18 |
}
|
| 19 |
return 0;
|
| 20 |
}
|
| 21 |
|
| 22 |
fn parse_modifiers(names: []const []const u8) u32 {
|
| 23 |
var mask: u32 = 0;
|
| 24 |
for (names) |name| {
|
| 25 |
mask |= parse_modifier(name);
|
| 26 |
}
|
| 27 |
return mask;
|
| 28 |
}
|
| 29 |
|
| 30 |
test "parse_modifier: Mod4 variants" {
|
| 31 |
try testing.expectEqual(Mod4Mask, parse_modifier("Mod4"));
|
| 32 |
try testing.expectEqual(Mod4Mask, parse_modifier("mod4"));
|
| 33 |
try testing.expectEqual(Mod4Mask, parse_modifier("super"));
|
| 34 |
}
|
| 35 |
|
| 36 |
test "parse_modifier: Mod1 (Alt) variants" {
|
| 37 |
try testing.expectEqual(Mod1Mask, parse_modifier("Mod1"));
|
| 38 |
try testing.expectEqual(Mod1Mask, parse_modifier("mod1"));
|
| 39 |
try testing.expectEqual(Mod1Mask, parse_modifier("alt"));
|
| 40 |
}
|
| 41 |
|
| 42 |
test "parse_modifier: Shift variants" {
|
| 43 |
try testing.expectEqual(ShiftMask, parse_modifier("Shift"));
|
| 44 |
try testing.expectEqual(ShiftMask, parse_modifier("shift"));
|
| 45 |
}
|
| 46 |
|
| 47 |
test "parse_modifier: Control variants" {
|
| 48 |
try testing.expectEqual(ControlMask, parse_modifier("Control"));
|
| 49 |
try testing.expectEqual(ControlMask, parse_modifier("control"));
|
| 50 |
try testing.expectEqual(ControlMask, parse_modifier("ctrl"));
|
| 51 |
}
|
| 52 |
|
| 53 |
test "parse_modifier: unknown returns 0" {
|
| 54 |
try testing.expectEqual(@as(u32, 0), parse_modifier("Unknown"));
|
| 55 |
try testing.expectEqual(@as(u32, 0), parse_modifier(""));
|
| 56 |
}
|
| 57 |
|
| 58 |
test "parse_modifiers: combines multiple modifiers" {
|
| 59 |
const mods = &[_][]const u8{ "Mod4", "Shift" };
|
| 60 |
try testing.expectEqual(Mod4Mask | ShiftMask, parse_modifiers(mods));
|
| 61 |
}
|
| 62 |
|
| 63 |
test "parse_modifiers: triple combination" {
|
| 64 |
const mods = &[_][]const u8{ "super", "shift", "ctrl" };
|
| 65 |
try testing.expectEqual(Mod4Mask | ShiftMask | ControlMask, parse_modifiers(mods));
|
| 66 |
}
|
| 67 |
|
| 68 |
test "parse_modifiers: empty list returns 0" {
|
| 69 |
const mods = &[_][]const u8{};
|
| 70 |
try testing.expectEqual(@as(u32, 0), parse_modifiers(mods));
|
| 71 |
}
|
| 72 |
|
| 73 |
fn key_name_to_keysym(name: []const u8) ?u64 {
|
| 74 |
const key_map = .{
|
| 75 |
.{ "Return", 0xff0d },
|
| 76 |
.{ "Enter", 0xff0d },
|
| 77 |
.{ "Tab", 0xff09 },
|
| 78 |
.{ "Escape", 0xff1b },
|
| 79 |
.{ "BackSpace", 0xff08 },
|
| 80 |
.{ "Delete", 0xffff },
|
| 81 |
.{ "space", 0x0020 },
|
| 82 |
.{ "Space", 0x0020 },
|
| 83 |
};
|
| 84 |
|
| 85 |
inline for (key_map) |entry| {
|
| 86 |
if (std.mem.eql(u8, name, entry[0])) {
|
| 87 |
return entry[1];
|
| 88 |
}
|
| 89 |
}
|
| 90 |
|
| 91 |
if (name.len == 1) {
|
| 92 |
const char = name[0];
|
| 93 |
if (char >= 'a' and char <= 'z') {
|
| 94 |
return char;
|
| 95 |
}
|
| 96 |
if (char >= 'A' and char <= 'Z') {
|
| 97 |
return char + 32;
|
| 98 |
}
|
| 99 |
if (char >= '0' and char <= '9') {
|
| 100 |
return char;
|
| 101 |
}
|
| 102 |
}
|
| 103 |
|
| 104 |
return null;
|
| 105 |
}
|
| 106 |
|
| 107 |
test "key_name_to_keysym: special keys" {
|
| 108 |
try testing.expectEqual(@as(?u64, 0xff0d), key_name_to_keysym("Return"));
|
| 109 |
try testing.expectEqual(@as(?u64, 0xff0d), key_name_to_keysym("Enter"));
|
| 110 |
try testing.expectEqual(@as(?u64, 0xff09), key_name_to_keysym("Tab"));
|
| 111 |
try testing.expectEqual(@as(?u64, 0xff1b), key_name_to_keysym("Escape"));
|
| 112 |
}
|
| 113 |
|
| 114 |
test "key_name_to_keysym: lowercase letters" {
|
| 115 |
try testing.expectEqual(@as(?u64, 'a'), key_name_to_keysym("a"));
|
| 116 |
try testing.expectEqual(@as(?u64, 'z'), key_name_to_keysym("z"));
|
| 117 |
}
|
| 118 |
|
| 119 |
test "key_name_to_keysym: uppercase converts to lowercase" {
|
| 120 |
try testing.expectEqual(@as(?u64, 'a'), key_name_to_keysym("A"));
|
| 121 |
try testing.expectEqual(@as(?u64, 'z'), key_name_to_keysym("Z"));
|
| 122 |
}
|
| 123 |
|
| 124 |
test "key_name_to_keysym: numbers" {
|
| 125 |
try testing.expectEqual(@as(?u64, '0'), key_name_to_keysym("0"));
|
| 126 |
try testing.expectEqual(@as(?u64, '9'), key_name_to_keysym("9"));
|
| 127 |
}
|
| 128 |
|
| 129 |
test "key_name_to_keysym: unknown returns null" {
|
| 130 |
try testing.expectEqual(@as(?u64, null), key_name_to_keysym("UnknownKey"));
|
| 131 |
try testing.expectEqual(@as(?u64, null), key_name_to_keysym(""));
|
| 132 |
}
|
| 133 |
|
| 134 |
test "key_name_to_keysym: space variants" {
|
| 135 |
try testing.expectEqual(@as(?u64, 0x0020), key_name_to_keysym("space"));
|
| 136 |
try testing.expectEqual(@as(?u64, 0x0020), key_name_to_keysym("Space"));
|
| 137 |
}
|