1 #ifndef keys_hh_INCLUDED
2 #define keys_hh_INCLUDED
3 
4 #include "coord.hh"
5 #include "flags.hh"
6 #include "hash.hh"
7 #include "meta.hh"
8 #include "optional.hh"
9 #include "unicode.hh"
10 #include "vector.hh"
11 
12 namespace Kakoune
13 {
14 
15 struct Key
16 {
17     enum class MouseButton
18     {
19         Left,
20         Middle,
21         Right
22     };
23     enum class Modifiers : int
24     {
25         None    = 0,
26         Control = 1 << 0,
27         Alt     = 1 << 1,
28         Shift   = 1 << 2,
29 
30         MousePress     = 1 << 3,
31         MouseRelease   = 1 << 4,
32         MousePos       = 1 << 5,
33         MouseButtonMask= 0b11 << 6,
34 
35         Scroll     = 1 << 8,
36         Resize     = 1 << 9,
37         MenuSelect = 1 << 10,
38     };
39     enum NamedKey : Codepoint
40     {
41         // use UTF-16 surrogate pairs range
42         Backspace = 0xD800,
43         Delete,
44         Escape,
45         Return,
46         Up,
47         Down,
48         Left,
49         Right,
50         PageUp,
51         PageDown,
52         Home,
53         End,
54         Insert,
55         Tab,
56         F1,
57         F2,
58         F3,
59         F4,
60         F5,
61         F6,
62         F7,
63         F8,
64         F9,
65         F10,
66         F11,
67         F12,
68         FocusIn,
69         FocusOut,
70         Invalid,
71     };
72 
73     Modifiers modifiers = {};
74     Codepoint key = {};
75 
KeyKakoune::Key76     constexpr Key(Modifiers modifiers, Codepoint key)
77         : modifiers(modifiers), key(key) {}
78 
KeyKakoune::Key79     constexpr Key(Codepoint key)
80         : modifiers(Modifiers::None), key(key) {}
81 
82     constexpr Key() = default;
83 
valKakoune::Key84     constexpr uint64_t val() const { return (uint64_t)modifiers << 32 | key; }
85 
operator ==Kakoune::Key86     constexpr bool operator==(Key other) const { return val() == other.val(); }
operator !=Kakoune::Key87     constexpr bool operator!=(Key other) const { return val() != other.val(); }
operator <Kakoune::Key88     constexpr bool operator<(Key other) const { return val() < other.val(); }
89 
coordKakoune::Key90     constexpr DisplayCoord coord() const { return {(int)((key & 0xFFFF0000) >> 16), (int)(key & 0x0000FFFF)}; }
mouse_buttonKakoune::Key91     constexpr MouseButton mouse_button() { return MouseButton{((int)modifiers & (int)Modifiers::MouseButtonMask) >> 6}; }
to_modifierKakoune::Key92     static Modifiers to_modifier(MouseButton button) { return Key::Modifiers{((int)button << 6) & (int)Modifiers::MouseButtonMask}; }
93 
94     Optional<Codepoint> codepoint() const;
95 };
96 
with_bit_ops(Meta::Type<Key::Modifiers>)97 constexpr bool with_bit_ops(Meta::Type<Key::Modifiers>) { return true; }
98 
99 using KeyList = Vector<Key, MemoryDomain::Mapping>;
100 
101 class String;
102 class StringView;
103 
104 KeyList parse_keys(StringView str);
105 String  key_to_str(Key key);
106 StringView button_to_str(Key::MouseButton button);
107 Key::MouseButton str_to_button(StringView str);
108 
shift(Key key)109 constexpr Key shift(Key key)
110 {
111     return { key.modifiers | Key::Modifiers::Shift, key.key };
112 }
alt(Key key)113 constexpr Key alt(Key key)
114 {
115     return { key.modifiers | Key::Modifiers::Alt, key.key };
116 }
ctrl(Key key)117 constexpr Key ctrl(Key key)
118 {
119     return { key.modifiers | Key::Modifiers::Control, key.key };
120 }
121 
encode_coord(DisplayCoord coord)122 constexpr Codepoint encode_coord(DisplayCoord coord) { return (Codepoint)(((int)coord.line << 16) | ((int)coord.column & 0x0000FFFF)); }
123 
resize(DisplayCoord dim)124 constexpr Key resize(DisplayCoord dim) { return { Key::Modifiers::Resize, encode_coord(dim) }; }
125 
hash_value(const Key & key)126 constexpr size_t hash_value(const Key& key) { return hash_values(key.modifiers, key.key); }
127 
128 }
129 
130 #endif // keys_hh_INCLUDED
131