tiny.xkb.state
Defined in tiny.xkb.
API (20)
Actions
Public operations.
Changes.anyState.consumedModifiersState.effectiveLayoutState.effectiveModifiersState.initState.keyRepeatsState.layoutState.levelState.modifierActiveState.modifierConsumedState.modifierIndexActiveState.oneSymbolState.symbolsState.updateState.writeUtf8
Types and contracts
Public types and contracts.
Source
Source: lib/xkb/src/state/model.zig:16
zig
pub const Changes = struct { depressed_modifiers: bool = false, latched_modifiers: bool = false, locked_modifiers: bool = false, effective_modifiers: bool = false, depressed_layout: bool = false, latched_layout: bool = false, locked_layout: bool = false, effective_layout: bool = false, pub fn any(self: Changes) bool { return self.depressed_modifiers or self.latched_modifiers or self.locked_modifiers or self.effective_modifiers or self.depressed_layout or self.latched_layout or self.locked_layout or self.effective_layout; }};Source: lib/xkb/src/state/model.zig:7
zig
pub const Mask = struct { depressed_modifiers: keymap.ModifierMask = 0, latched_modifiers: keymap.ModifierMask = 0, locked_modifiers: keymap.ModifierMask = 0, depressed_layout: u32 = 0, latched_layout: u32 = 0, locked_layout: u32 = 0,};Source: lib/xkb/src/state/model.zig:34
zig
pub const ModifierComponents = struct { depressed: bool = false, latched: bool = false, locked: bool = false, effective: bool = false,};Source: lib/xkb/src/state/model.zig:54
zig
pub const State = struct { keymap: *const keymap.Keymap, components: Components = .{}, pub fn init(compiled: *const keymap.Keymap) State { return .{ .keymap = compiled }; } pub fn update(self: *State, input: Mask) Changes { const previous = self.components; self.components.depressed_modifiers = self.keymap.resolveToCanonicalModifiers(input.depressed_modifiers); self.components.latched_modifiers = self.keymap.resolveToCanonicalModifiers(input.latched_modifiers); self.components.locked_modifiers = self.keymap.resolveToCanonicalModifiers(input.locked_modifiers); self.components.effective_modifiers = self.components.depressed_modifiers | self.components.latched_modifiers | self.components.locked_modifiers; self.components.depressed_layout = @bitCast(input.depressed_layout); self.components.latched_layout = @bitCast(input.latched_layout); self.components.locked_layout = layoutInRange(@bitCast(input.locked_layout), self.keymap.layoutCount()); const layout_sum = self.components.depressed_layout +% self.components.latched_layout +% self.components.locked_layout; self.components.effective_layout = layoutInRange(layout_sum, self.keymap.layoutCount()); return changes(previous, self.components); } pub fn effectiveModifiers(self: *const State) keymap.ModifierMask { return self.components.effective_modifiers; } pub fn effectiveLayout(self: *const State) usize { return @intCast(self.components.effective_layout); } pub fn modifierActive(self: *const State, name: []const u8) bool { const index = self.keymap.modifierIndex(name) orelse return false; return self.modifierIndexActive(index, .{ .effective = true }); } pub fn modifierIndexActive( self: *const State, index: usize, requested: ModifierComponents, ) bool { const mapping = self.keymap.modifierMapping(index) orelse return false; if (mapping == 0) return false; const active = self.serializeModifiers(requested); return active & mapping == mapping; } pub fn keyRepeats(self: *const State, code: keymap.Keycode) bool { const key_value = self.keymap.key(code) orelse return false; return key_value.repeats; } pub fn layout(self: *const State, code: keymap.Keycode) ?usize { const key_value = self.keymap.key(code) orelse return null; return self.keymap.group(key_value, self.components.effective_layout); } pub fn level(self: *const State, code: keymap.Keycode) ?usize { const key_value = self.keymap.key(code) orelse return null; const group_index = self.keymap.group(key_value, self.components.effective_layout) orelse return null; return self.levelForGroup(key_value, group_index); } pub fn symbols(self: *const State, code: keymap.Keycode) []const keysym.Keysym { const selection_value = self.selection(code) orelse return &.{}; return selection_value.level.resolvedSymbols(self.capsTransforms(code)); } pub fn oneSymbol(self: *const State, code: keymap.Keycode) ?keysym.Keysym { const selected = self.symbols(code); if (selected.len != 1) return null; return selected[0]; } pub fn consumedModifiers(self: *const State, code: keymap.Keycode) keymap.ModifierMask { const selection_value = self.selection(code) orelse return 0; const key_type = self.keymap.keyType(selection_value.group.type_index).?; const active = self.components.effective_modifiers & key_type.modifiers; var preserve: keymap.ModifierMask = 0; for (key_type.entries) |entry| { if (entry.modifiers == active) { preserve = entry.preserve; break; } } return key_type.modifiers & ~preserve; } pub fn modifierConsumed(self: *const State, code: keymap.Keycode, name: []const u8) bool { const index = self.keymap.modifierIndex(name) orelse return false; const mapping = self.keymap.modifierMapping(index) orelse return false; if (mapping == 0) return false; return self.consumedModifiers(code) & mapping == mapping; } pub fn writeUtf8( self: *const State, code: keymap.Keycode, buffer: []u8, ) TextError!?[]const u8 { const control = self.controlTransforms(code); if (self.oneSymbolForText(code, control)) |symbol| { const written = try writeSymbol(symbol, buffer); if (written == 0) return null; if (written == 1 and control) buffer[0] = toControl(buffer[0]); return buffer[0..written]; } const selected = self.symbols(code); if (selected.len == 0) return null; var written: usize = 0; for (selected) |symbol| { const count = try writeSymbol(symbol, buffer[written..]); if (count == 0) return null; written += count; } if (written == 1 and control) buffer[0] = toControl(buffer[0]); return buffer[0..written]; } fn serializeModifiers(self: *const State, requested: ModifierComponents) keymap.ModifierMask { if (requested.effective) return self.components.effective_modifiers; var result: keymap.ModifierMask = 0; if (requested.depressed) result |= self.components.depressed_modifiers; if (requested.latched) result |= self.components.latched_modifiers; if (requested.locked) result |= self.components.locked_modifiers; return result; } fn selection(self: *const State, code: keymap.Keycode) ?Selection { const key_value = self.keymap.key(code) orelse return null; const group_index = self.keymap.group(key_value, self.components.effective_layout) orelse return null; const group = &key_value.groups[group_index]; const level_index = self.levelForGroup(key_value, group_index); if (level_index >= group.levels.len) return null; return .{ .key = key_value, .group = group, .level = &group.levels[level_index], }; } fn levelForGroup(self: *const State, key_value: *const keymap.Key, group_index: usize) usize { const group = key_value.groups[group_index]; const key_type = self.keymap.keyType(group.type_index).?; const active = self.components.effective_modifiers & key_type.modifiers; for (key_type.entries) |entry| { if (entry.modifiers == active) return entry.level; } return 0; } fn capsTransforms(self: *const State, code: keymap.Keycode) bool { return self.modifierActive("Lock") and !self.modifierConsumed(code, "Lock"); } fn controlTransforms(self: *const State, code: keymap.Keycode) bool { return self.modifierActive("Control") and !self.modifierConsumed(code, "Control"); } fn oneSymbolForText( self: *const State, code: keymap.Keycode, control: bool, ) ?keysym.Keysym { const selected = self.selection(code) orelse return null; if (selected.level.symbols.len != 1) return null; var selected_level = selected.level; if (control and @backingInt(selected_level.symbols[0]) > 127) { for (selected.key.groups, 0..) |group, group_index| { const level_index = self.levelForGroup(selected.key, group_index); if (level_index >= group.levels.len) continue; const candidates = group.levels[level_index].symbols; if (candidates.len == 1 and @backingInt(candidates[0]) <= 127) { selected_level = &group.levels[level_index]; break; } } } const resolved = selected_level.resolvedSymbols(self.capsTransforms(code)); return resolved[0]; }};Source: lib/xkb/src/state/model.zig:41
zig
pub const TextError = error{BufferTooSmall};Source: lib/xkb/src/root.zig:52
zig
pub const state = @import("state/root.zig");Source: lib/xkb/src/state/root.zig
zig
const model = @import("model.zig");pub const Mask = model.Mask;pub const Changes = model.Changes;pub const ModifierComponents = model.ModifierComponents;pub const TextError = model.TextError;pub const State = model.State;Complete caller list for state.State.init
7 direct callers.
lib.xkb.src.state.model.test_caps_preserve_and_control_transformations_match_XKB_text_semantics[function] — test source atlib/xkb/src/state/model.zig:349in nearest public ownerlib.xkb.src.state.modellib.xkb.src.state.model.test_effective_layout_and_per-key_group_rules_are_distinct[function] — test source atlib/xkb/src/state/model.zig:381in nearest public ownerlib.xkb.src.state.modellib.xkb.src.state.model.test_empty_keymaps_retain_canonical_core_modifiers[function] — test source atlib/xkb/src/state/model.zig:392in nearest public ownerlib.xkb.src.state.modellib.xkb.src.state.model.test_external_masks_select_levels_and_report_state_changes[function] — test source atlib/xkb/src/state/model.zig:332in nearest public ownerlib.xkb.src.state.modellib.xkb.src.state.model.test_multi-symbol_levels_concatenate_Unicode_and_preserve_one-symbol_absence[function] — test source atlib/xkb/src/state/model.zig:369in nearest public ownerlib.xkb.src.state.modellib.xkb.src.state.model.test_repeat-only_keys_expose_no_layout_level_or_symbols[function] — test source atlib/xkb/src/state/model.zig:409in nearest public ownerlib.xkb.src.state.modellib.xkb.src.state.model.test_symbols_exposes_the_canonical_transformed_sequence[function] — test source atlib/xkb/src/state/model.zig:424in nearest public ownerlib.xkb.src.state.model
Audit
| Definitions | 21 |
|---|---|
| Public names | 21 |
| Members | 21 |
| Version | 26.7.0 |
| Revision | daab053ee433 |