[READ-ONLY] Mirror of https://github.com/bombshell-dev/tty. Platform independent 2D layout engine for terminal applications based on Clay
0

Configure Feed

Select the types of activity you want to include in your feed.

tty / input-native.ts
6.3 kB 224 lines
1export const EVENT_KEY = 1; 2export const EVENT_MOUSE = 2; 3export const EVENT_RESIZE = 3; 4export const EVENT_CURSOR = 4; 5 6export const MOD_ALT = 1; 7export const MOD_CTRL = 2; 8export const MOD_SHIFT = 4; 9export const MOD_MOTION = 8; 10export const MOD_RELEASE = 16; 11 12export const KEY_F1 = 0xFFFF; 13export const KEY_F2 = 0xFFFE; 14export const KEY_F3 = 0xFFFD; 15export const KEY_F4 = 0xFFFC; 16export const KEY_F5 = 0xFFFB; 17export const KEY_F6 = 0xFFFA; 18export const KEY_F7 = 0xFFF9; 19export const KEY_F8 = 0xFFF8; 20export const KEY_F9 = 0xFFF7; 21export const KEY_F10 = 0xFFF6; 22export const KEY_F11 = 0xFFF5; 23export const KEY_F12 = 0xFFF4; 24export const KEY_ARROW_UP = 0xFFF3; 25export const KEY_ARROW_DOWN = 0xFFF2; 26export const KEY_ARROW_LEFT = 0xFFF1; 27export const KEY_ARROW_RIGHT = 0xFFF0; 28export const KEY_HOME = 0xFFEF; 29export const KEY_END = 0xFFEE; 30export const KEY_INSERT = 0xFFED; 31export const KEY_DELETE = 0xFFEC; 32export const KEY_PGUP = 0xFFEB; 33export const KEY_PGDN = 0xFFEA; 34export const KEY_BACKTAB = 0xFFE9; 35export const KEY_NUMPAD_0 = 0xFFE2; 36export const KEY_NUMPAD_1 = 0xFFE1; 37export const KEY_NUMPAD_2 = 0xFFE0; 38export const KEY_NUMPAD_3 = 0xFFDF; 39export const KEY_NUMPAD_4 = 0xFFDE; 40export const KEY_NUMPAD_5 = 0xFFDD; 41export const KEY_NUMPAD_6 = 0xFFDC; 42export const KEY_NUMPAD_7 = 0xFFDB; 43export const KEY_NUMPAD_8 = 0xFFDA; 44export const KEY_NUMPAD_9 = 0xFFD9; 45export const KEY_NUMPAD_DECIMAL = 0xFFD8; 46export const KEY_NUMPAD_DIVIDE = 0xFFD7; 47export const KEY_NUMPAD_MULTIPLY = 0xFFD6; 48export const KEY_NUMPAD_SUBTRACT = 0xFFD5; 49export const KEY_NUMPAD_ADD = 0xFFD4; 50export const KEY_NUMPAD_ENTER = 0xFFD3; 51export const KEY_NUMPAD_EQUAL = 0xFFD2; 52 53export const KEY_SHIFT_LEFT = 0xFFD1; 54export const KEY_SHIFT_RIGHT = 0xFFD0; 55export const KEY_CONTROL_LEFT = 0xFFCF; 56export const KEY_CONTROL_RIGHT = 0xFFCE; 57export const KEY_ALT_LEFT = 0xFFCD; 58export const KEY_ALT_RIGHT = 0xFFCC; 59export const KEY_SUPER_LEFT = 0xFFCB; 60export const KEY_SUPER_RIGHT = 0xFFCA; 61export const KEY_HYPER_LEFT = 0xFFC9; 62export const KEY_HYPER_RIGHT = 0xFFC8; 63export const KEY_META_LEFT = 0xFFC7; 64export const KEY_META_RIGHT = 0xFFC6; 65export const KEY_CAPS_LOCK = 0xFFC5; 66export const KEY_NUM_LOCK = 0xFFC4; 67export const KEY_SCROLL_LOCK = 0xFFC3; 68 69export const KEY_MOUSE_LEFT = 0xFFE8; 70export const KEY_MOUSE_RIGHT = 0xFFE7; 71export const KEY_MOUSE_MIDDLE = 0xFFE6; 72export const KEY_MOUSE_RELEASE = 0xFFE5; 73export const KEY_MOUSE_WHEEL_UP = 0xFFE4; 74export const KEY_MOUSE_WHEEL_DOWN = 0xFFE3; 75export const KEY_ESC = 0x1B; 76export const KEY_ENTER = 0x0D; 77export const KEY_TAB = 0x09; 78export const KEY_BACKSPACE = 0x7F; 79export const KEY_SPACE = 0x20; 80 81import { 82 array, 83 int32, 84 offsets, 85 struct, 86 uint16, 87 uint32, 88 uint8, 89} from "./typedef.ts"; 90 91const MAX_TEXT_CODEPOINTS = 8; 92 93const InputEventLayout = struct({ 94 type: uint8(), 95 mod: uint8(), 96 key: uint16(), 97 ch: uint32(), 98 x: int32(), 99 y: int32(), 100 w: int32(), 101 h: int32(), 102 action: uint8(), 103 shifted: uint32(), 104 base: uint32(), 105 text: array(uint32(), MAX_TEXT_CODEPOINTS), 106 text_len: uint8(), 107}); 108 109const { 110 type: OFFSET_TYPE, 111 mod: OFFSET_MOD, 112 key: OFFSET_KEY, 113 ch: OFFSET_CH, 114 x: OFFSET_X, 115 y: OFFSET_Y, 116 w: OFFSET_W, 117 h: OFFSET_H, 118 action: OFFSET_ACTION, 119 text_len: OFFSET_TEXT_LEN, 120 shifted: OFFSET_SHIFTED, 121 base: OFFSET_BASE, 122 text: OFFSET_TEXT, 123} = offsets(InputEventLayout); 124 125export interface NativeInputEvent { 126 type: number; 127 mod: number; 128 key: number; 129 ch: number; 130 x: number; 131 y: number; 132 w: number; 133 h: number; 134 action: number; 135 shifted: number; 136 base: number; 137 text: number[]; 138} 139 140export function readEvent(view: DataView, ptr: number): NativeInputEvent { 141 let len = view.getUint8(ptr + OFFSET_TEXT_LEN); 142 let text: number[] = []; 143 for (let i = 0; i < len && i < MAX_TEXT_CODEPOINTS; i++) { 144 text.push(view.getUint32(ptr + OFFSET_TEXT + i * 4, true)); 145 } 146 return { 147 type: view.getUint8(ptr + OFFSET_TYPE), 148 mod: view.getUint8(ptr + OFFSET_MOD), 149 key: view.getUint16(ptr + OFFSET_KEY, true), 150 ch: view.getUint32(ptr + OFFSET_CH, true), 151 x: view.getInt32(ptr + OFFSET_X, true), 152 y: view.getInt32(ptr + OFFSET_Y, true), 153 w: view.getInt32(ptr + OFFSET_W, true), 154 h: view.getInt32(ptr + OFFSET_H, true), 155 action: view.getUint8(ptr + OFFSET_ACTION), 156 shifted: view.getUint32(ptr + OFFSET_SHIFTED, true), 157 base: view.getUint32(ptr + OFFSET_BASE, true), 158 text, 159 }; 160} 161 162export interface InputNative { 163 memory: WebAssembly.Memory; 164 state: number; 165 buffer: number; 166 scan(st: number, buf: number, len: number, now: number): number; 167 count(st: number): number; 168 event(st: number, index: number): number; 169 delay(st: number): number; 170} 171 172import { compiled } from "./wasm.ts"; 173 174export async function createInputNative( 175 escLatency: number, 176): Promise<InputNative> { 177 let memory = new WebAssembly.Memory({ initial: 4 }); 178 179 let instance = await WebAssembly.instantiate(compiled, { 180 env: { memory }, 181 clay: { 182 measureTextFunction() {}, 183 queryScrollOffsetFunction(ret: number) { 184 let v = new DataView(memory.buffer); 185 v.setFloat32(ret, 0, true); 186 v.setFloat32(ret + 4, 0, true); 187 }, 188 }, 189 }); 190 191 let exports = instance.exports as unknown as { 192 __heap_base: WebAssembly.Global; 193 input_size(): number; 194 input_init(mem: number, escLatency: number): number; 195 input_scan(st: number, buf: number, len: number, now: number): number; 196 input_count(st: number): number; 197 input_event(st: number, index: number): number; 198 input_delay(st: number): number; 199 }; 200 201 let heap = exports.__heap_base.value as number; 202 let size = exports.input_size(); 203 let state = exports.input_init(heap, escLatency); 204 let buffer = (heap + size + 7) & ~7; 205 206 return { 207 memory, 208 state, 209 buffer, 210 scan: exports.input_scan, 211 count: exports.input_count, 212 event: exports.input_event, 213 delay: exports.input_delay, 214 }; 215} 216 217// Compiled terminfo entries are limited to 4096 bytes (legacy) or 32768 218// bytes (extended ncurses format). We use the extended limit as our upper 219// bound. See https://man7.org/linux/man-pages/man5/term.5.html 220export const MAX_TERMINFO = 32768; 221 222// Must match SCAN_BUFFER_SIZE in input.c — the maximum bytes input_scan() 223// can accept in a single call. 224export const SCAN_BUFFER_SIZE = 4096;