Port mouse event encoding code to C
This commit is contained in:
parent
b9ac13c379
commit
43c4c71abd
@ -237,3 +237,30 @@ decode_utf8(uint32_t* state, uint32_t* codep, uint8_t byte) {
|
||||
*state = utf8_data[256 + *state*16 + type];
|
||||
return *state;
|
||||
}
|
||||
|
||||
unsigned int
|
||||
encode_utf8(uint32_t ch, char* dest) {
|
||||
if (ch < 0x80) {
|
||||
dest[0] = (char)ch;
|
||||
return 1;
|
||||
}
|
||||
if (ch < 0x800) {
|
||||
dest[0] = (ch>>6) | 0xC0;
|
||||
dest[1] = (ch & 0x3F) | 0x80;
|
||||
return 2;
|
||||
}
|
||||
if (ch < 0x10000) {
|
||||
dest[0] = (ch>>12) | 0xE0;
|
||||
dest[1] = ((ch>>6) & 0x3F) | 0x80;
|
||||
dest[2] = (ch & 0x3F) | 0x80;
|
||||
return 3;
|
||||
}
|
||||
if (ch < 0x110000) {
|
||||
dest[0] = (ch>>18) | 0xF0;
|
||||
dest[1] = ((ch>>12) & 0x3F) | 0x80;
|
||||
dest[2] = ((ch>>6) & 0x3F) | 0x80;
|
||||
dest[3] = (ch & 0x3F) | 0x80;
|
||||
return 4;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -296,6 +296,7 @@ void parse_worker_dump(Screen *screen, PyObject *dump_callback);
|
||||
PyObject* parse_bytes_dump(PyObject UNUSED *, PyObject *);
|
||||
PyObject* parse_bytes(PyObject UNUSED *, PyObject *);
|
||||
uint32_t decode_utf8(uint32_t*, uint32_t*, uint8_t byte);
|
||||
unsigned int encode_utf8(uint32_t ch, char* dest);
|
||||
void cursor_reset(Cursor*);
|
||||
Cursor* cursor_copy(Cursor*);
|
||||
void cursor_copy_to(Cursor *src, Cursor *dest);
|
||||
|
||||
@ -8,11 +8,13 @@
|
||||
#include "state.h"
|
||||
#include "screen.h"
|
||||
#include "lineops.h"
|
||||
#include <limits.h>
|
||||
#include <math.h>
|
||||
#include <GLFW/glfw3.h>
|
||||
|
||||
extern void set_mouse_cursor(MouseShape);
|
||||
static MouseShape mouse_cursor_shape = BEAM;
|
||||
typedef enum MouseActions { PRESS, RELEASE, DRAG, MOVE } MouseAction;
|
||||
|
||||
#define call_boss(name, ...) { \
|
||||
PyObject *cret_ = PyObject_CallMethod(global_state.boss, #name, __VA_ARGS__); \
|
||||
@ -20,6 +22,74 @@ static MouseShape mouse_cursor_shape = BEAM;
|
||||
else Py_DECREF(cret_); \
|
||||
}
|
||||
|
||||
#define SHIFT_INDICATOR (1 << 2)
|
||||
#define ALT_INDICATOR (1 << 3)
|
||||
#define CONTROL_INDICATOR (1 << 4)
|
||||
#define MOTION_INDICATOR (1 << 5)
|
||||
#define EXTRA_BUTTON_INDICATOR (1 << 6)
|
||||
|
||||
static inline unsigned int
|
||||
button_map(int button) {
|
||||
switch(button) {
|
||||
case GLFW_MOUSE_BUTTON_1:
|
||||
return 0;
|
||||
case GLFW_MOUSE_BUTTON_2:
|
||||
return 1;
|
||||
case GLFW_MOUSE_BUTTON_3:
|
||||
return 2;
|
||||
case GLFW_MOUSE_BUTTON_4:
|
||||
return EXTRA_BUTTON_INDICATOR;
|
||||
case GLFW_MOUSE_BUTTON_5:
|
||||
return EXTRA_BUTTON_INDICATOR | 1;
|
||||
default:
|
||||
return UINT_MAX;
|
||||
}
|
||||
}
|
||||
|
||||
static char mouse_event_buf[64];
|
||||
|
||||
unsigned int
|
||||
encode_mouse_event(Window *w, int button, MouseAction action, int mods) {
|
||||
unsigned int x = w->mouse_cell_x + 1, y = w->mouse_cell_y + 1; // 1 based indexing
|
||||
unsigned int cb = 0;
|
||||
Screen *screen = w->render_data.screen;
|
||||
|
||||
if (action == MOVE) {
|
||||
if (screen->modes.mouse_tracking_protocol != SGR_PROTOCOL) cb = 3;
|
||||
} else {
|
||||
cb = button_map(button);
|
||||
if (cb == UINT_MAX) return 0;
|
||||
}
|
||||
if (action == DRAG || action == MOVE) cb |= MOTION_INDICATOR;
|
||||
else if (action == RELEASE && screen->modes.mouse_tracking_protocol != SGR_PROTOCOL) cb = 3;
|
||||
if (mods & GLFW_MOD_SHIFT) cb |= SHIFT_INDICATOR;
|
||||
if (mods & GLFW_MOD_ALT) cb |= ALT_INDICATOR;
|
||||
if (mods & GLFW_MOD_CONTROL) cb |= CONTROL_INDICATOR;
|
||||
switch(screen->modes.mouse_tracking_protocol) {
|
||||
case SGR_PROTOCOL:
|
||||
return snprintf(mouse_event_buf, sizeof(mouse_event_buf), "\033[<%d;%d;%d%s", cb, x, y, action == RELEASE ? "m" : "M");
|
||||
break;
|
||||
case URXVT_PROTOCOL:
|
||||
return snprintf(mouse_event_buf, sizeof(mouse_event_buf), "\033[%d;%d;%dM", cb, x, y);
|
||||
break;
|
||||
case UTF8_PROTOCOL:
|
||||
mouse_event_buf[0] = 033; mouse_event_buf[1] = '['; mouse_event_buf[2] = cb + 32;
|
||||
unsigned int sz = 3;
|
||||
sz += encode_utf8(x + 32, mouse_event_buf + sz);
|
||||
sz += encode_utf8(y + 32, mouse_event_buf + sz);
|
||||
return sz;
|
||||
break;
|
||||
default:
|
||||
if (x > 223 || y > 223) return 0;
|
||||
else {
|
||||
mouse_event_buf[0] = 033; mouse_event_buf[1] = '['; mouse_event_buf[2] = 'M'; mouse_event_buf[3] = cb + 32; mouse_event_buf[4] = x + 32; mouse_event_buf[5] = y + 32;
|
||||
return 6;
|
||||
}
|
||||
break;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline bool
|
||||
contains_mouse(Window *w) {
|
||||
WindowGeometry *g = &w->geometry;
|
||||
|
||||
@ -1,62 +0,0 @@
|
||||
#!/usr/bin/env python
|
||||
# vim:fileencoding=utf-8
|
||||
# License: GPL v3 Copyright: 2016, Kovid Goyal <kovid at kovidgoyal.net>
|
||||
|
||||
from .fast_data_types import (
|
||||
GLFW_MOUSE_BUTTON_2, GLFW_MOUSE_BUTTON_3, GLFW_MOD_ALT, GLFW_MOD_CONTROL,
|
||||
GLFW_MOD_SHIFT, GLFW_MOUSE_BUTTON_4, GLFW_MOUSE_BUTTON_5,
|
||||
GLFW_MOUSE_BUTTON_1,
|
||||
)
|
||||
|
||||
PRESS, RELEASE, DRAG, MOVE = range(4)
|
||||
SHIFT_INDICATOR = 1 << 2
|
||||
ALT_INDICATOR = 1 << 3
|
||||
CONTROL_INDICATOR = 1 << 4
|
||||
MOTION_INDICATOR = 1 << 5
|
||||
EXTRA_BUTTON_INDICATOR = 1 << 6
|
||||
|
||||
cb_map = {
|
||||
GLFW_MOUSE_BUTTON_1: 0,
|
||||
GLFW_MOUSE_BUTTON_2: 0b1,
|
||||
GLFW_MOUSE_BUTTON_3: 0b10,
|
||||
GLFW_MOUSE_BUTTON_4: EXTRA_BUTTON_INDICATOR,
|
||||
GLFW_MOUSE_BUTTON_5: EXTRA_BUTTON_INDICATOR | 0b1
|
||||
}
|
||||
|
||||
|
||||
def encode_mouse_event(tracking_mode, tracking_protocol, button, action, mods, x, y):
|
||||
x, y = x + 1, y + 1 # One based indexing
|
||||
cb = 0
|
||||
if action is MOVE:
|
||||
if tracking_protocol != SGR_PROTOCOL:
|
||||
cb = 0b11
|
||||
else:
|
||||
cb = cb_map.get(button)
|
||||
if cb is None:
|
||||
return
|
||||
if action in (DRAG, MOVE):
|
||||
cb |= MOTION_INDICATOR
|
||||
elif action is RELEASE:
|
||||
if tracking_protocol != SGR_PROTOCOL:
|
||||
cb = 0b11
|
||||
if mods & GLFW_MOD_SHIFT:
|
||||
cb |= SHIFT_INDICATOR
|
||||
if mods & GLFW_MOD_ALT:
|
||||
cb |= ALT_INDICATOR
|
||||
if mods & GLFW_MOD_CONTROL:
|
||||
cb |= CONTROL_INDICATOR
|
||||
ans = None
|
||||
if tracking_protocol == SGR_PROTOCOL:
|
||||
ans = '\033[<%d;%d;%d%s' % (cb, x, y, 'm' if action is RELEASE else 'M')
|
||||
ans = ans.encode('ascii')
|
||||
elif tracking_protocol == URXVT_PROTOCOL:
|
||||
ans = '\033[%d;%d;%dM' % (cb + 32, x, y)
|
||||
ans = ans.encode('ascii')
|
||||
elif tracking_protocol == UTF8_PROTOCOL:
|
||||
ans = bytearray([0o33, ord('['), cb + 32])
|
||||
ans.extend(chr(x + 32).encode('utf-8') + chr(y + 32).encode('utf-8'))
|
||||
ans = bytes(ans)
|
||||
else:
|
||||
if x <= 223 and y <= 223:
|
||||
ans = bytearray([0o33, ord('['), ord('M'), cb + 32, x + 32, y + 32])
|
||||
return ans
|
||||
@ -26,7 +26,6 @@ from .fast_data_types import (
|
||||
update_window_title, update_window_visibility
|
||||
)
|
||||
from .keys import get_key_map
|
||||
from .mouse import DRAG, MOVE, PRESS, RELEASE, encode_mouse_event
|
||||
from .rgb import to_color
|
||||
from .terminfo import get_capabilities
|
||||
from .utils import (
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user