aboutsummaryrefslogtreecommitdiff
path: root/hikari/menu/input.zig
blob: 34fa2a9c6d8e2aef2205848f17eb65f5b3574966 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
//! Hikari Menu Input

const efi = @import("../efi/efi.zig");

pub const InputAction = enum {
    none,
    up,
    down,
    select,
    cancel,
    page_up,
    page_down,
    home,
    end,
};

pub const Input = struct {
    system_table: *efi.services.SystemTable,

    pub fn initialize(system_table: *efi.services.SystemTable) Input {
        return Input{
            .system_table = system_table,
        };
    }

    pub fn poll(self: *Input) InputAction {
        var key: efi.types.input.InputKey = undefined;
        const status = self.system_table.console_input.read_key_stroke(
            self.system_table.console_input,
            &key,
        );

        if (efi.types.is_error(status)) {
            return .none;
        }

        if (key.scan_code != 0) {
            return switch (key.scan_code) {
                efi.constants.keyboard.scan_up => .up,
                efi.constants.keyboard.scan_down => .down,
                efi.constants.keyboard.scan_escape => .cancel,
                efi.constants.keyboard.scan_page_up => .page_up,
                efi.constants.keyboard.scan_page_down => .page_down,
                efi.constants.keyboard.scan_home => .home,
                efi.constants.keyboard.scan_end => .end,
                else => .none,
            };
        }

        if (key.unicode_char != 0) {
            return switch (key.unicode_char) {
                '\r', ' ' => .select,
                'j', 'J' => .down,
                'k', 'K' => .up,
                'q', 'Q' => .cancel,
                else => .none,
            };
        }

        return .none;
    }

    pub fn wait_for_key(self: *Input) void {
        var index: usize = 0;
        const events = [_]efi.types.Event{self.system_table.console_input.wait_for_key};
        _ = self.system_table.boot_services.wait_for_event(1, &events, &index);
    }

    pub fn wait_for_action(self: *Input) InputAction {
        while (true) {
            const action = self.poll();
            if (action != .none) {
                return action;
            }
            self.wait_for_key();
        }
    }

    pub fn clear_input_buffer(self: *Input) void {
        while (self.poll() != .none) {}
    }
};