Port drag select to C
This commit is contained in:
parent
cf6894d74f
commit
a27004da35
@ -197,13 +197,6 @@ PyInit_fast_data_types(void) {
|
|||||||
PyModule_AddIntMacro(m, DECCOLM);
|
PyModule_AddIntMacro(m, DECCOLM);
|
||||||
PyModule_AddIntMacro(m, DECOM);
|
PyModule_AddIntMacro(m, DECOM);
|
||||||
PyModule_AddIntMacro(m, IRM);
|
PyModule_AddIntMacro(m, IRM);
|
||||||
PyModule_AddIntMacro(m, ANY_MODE);
|
|
||||||
PyModule_AddIntMacro(m, MOTION_MODE);
|
|
||||||
PyModule_AddIntMacro(m, BUTTON_MODE);
|
|
||||||
PyModule_AddIntMacro(m, SGR_PROTOCOL);
|
|
||||||
PyModule_AddIntMacro(m, NORMAL_PROTOCOL);
|
|
||||||
PyModule_AddIntMacro(m, URXVT_PROTOCOL);
|
|
||||||
PyModule_AddIntMacro(m, UTF8_PROTOCOL);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return m;
|
return m;
|
||||||
|
|||||||
@ -32,13 +32,8 @@ typedef uint16_t sprite_index;
|
|||||||
typedef enum CursorShapes { NO_CURSOR_SHAPE, CURSOR_BLOCK, CURSOR_BEAM, CURSOR_UNDERLINE, NUM_OF_CURSOR_SHAPES } CursorShape;
|
typedef enum CursorShapes { NO_CURSOR_SHAPE, CURSOR_BLOCK, CURSOR_BEAM, CURSOR_UNDERLINE, NUM_OF_CURSOR_SHAPES } CursorShape;
|
||||||
|
|
||||||
#define ERROR_PREFIX "[PARSE ERROR]"
|
#define ERROR_PREFIX "[PARSE ERROR]"
|
||||||
#define ANY_MODE 3
|
typedef enum MouseTrackingModes { NO_TRACKING, BUTTON_MODE, MOTION_MODE, ANY_MODE } MouseTrackingMode;
|
||||||
#define MOTION_MODE 2
|
typedef enum MouseTrackingProtocols { NORMAL_PROTOCOL, UTF8_PROTOCOL, SGR_PROTOCOL, URXVT_PROTOCOL} MouseTrackingProtocol;
|
||||||
#define BUTTON_MODE 1
|
|
||||||
#define NORMAL_PROTOCOL 0
|
|
||||||
#define UTF8_PROTOCOL 1
|
|
||||||
#define SGR_PROTOCOL 2
|
|
||||||
#define URXVT_PROTOCOL 3
|
|
||||||
|
|
||||||
#define MAX_CHILDREN 256
|
#define MAX_CHILDREN 256
|
||||||
#define BLANK_CHAR 0
|
#define BLANK_CHAR 0
|
||||||
@ -197,7 +192,8 @@ PyTypeObject ColorProfile_Type;
|
|||||||
typedef struct {
|
typedef struct {
|
||||||
bool mLNM, mIRM, mDECTCEM, mDECSCNM, mDECOM, mDECAWM, mDECCOLM, mDECARM, mDECCKM,
|
bool mLNM, mIRM, mDECTCEM, mDECSCNM, mDECOM, mDECAWM, mDECCOLM, mDECARM, mDECCKM,
|
||||||
mBRACKETED_PASTE, mFOCUS_TRACKING, mEXTENDED_KEYBOARD;
|
mBRACKETED_PASTE, mFOCUS_TRACKING, mEXTENDED_KEYBOARD;
|
||||||
unsigned long mouse_tracking_mode, mouse_tracking_protocol;
|
MouseTrackingMode mouse_tracking_mode;
|
||||||
|
MouseTrackingProtocol mouse_tracking_protocol;
|
||||||
} ScreenModes;
|
} ScreenModes;
|
||||||
PyTypeObject ScreenModes_Type;
|
PyTypeObject ScreenModes_Type;
|
||||||
|
|
||||||
|
|||||||
@ -16,6 +16,10 @@
|
|||||||
#error "glfw >= 3.2 required"
|
#error "glfw >= 3.2 required"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#if GLFW_KEY_LAST >= MAX_KEY_COUNT
|
||||||
|
#error "glfw has too many keys, you should increase MAX_KEY_COUNT"
|
||||||
|
#endif
|
||||||
|
|
||||||
#define MAX_WINDOWS 256
|
#define MAX_WINDOWS 256
|
||||||
|
|
||||||
#define CALLBACK(name, fmt, ...) \
|
#define CALLBACK(name, fmt, ...) \
|
||||||
@ -59,6 +63,7 @@ char_mods_callback(GLFWwindow UNUSED *w, unsigned int codepoint, int mods) {
|
|||||||
static void
|
static void
|
||||||
key_callback(GLFWwindow UNUSED *w, int key, int scancode, int action, int mods) {
|
key_callback(GLFWwindow UNUSED *w, int key, int scancode, int action, int mods) {
|
||||||
global_state.cursor_blink_zero_time = monotonic();
|
global_state.cursor_blink_zero_time = monotonic();
|
||||||
|
if (key >= 0 && key <= GLFW_KEY_LAST) global_state.is_key_pressed[key] = action == GLFW_RELEASE ? false : true;
|
||||||
WINDOW_CALLBACK(key_callback, "iiii", key, scancode, action, mods);
|
WINDOW_CALLBACK(key_callback, "iiii", key, scancode, action, mods);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -40,14 +40,37 @@ cell_for_pos(Window *w, unsigned int *x, unsigned int *y) {
|
|||||||
|
|
||||||
#define HANDLER(name) static inline void name(Window UNUSED *w, int UNUSED button, int UNUSED modifiers, unsigned int UNUSED window_idx)
|
#define HANDLER(name) static inline void name(Window UNUSED *w, int UNUSED button, int UNUSED modifiers, unsigned int UNUSED window_idx)
|
||||||
|
|
||||||
|
static inline void
|
||||||
|
update_drag(bool from_button, Window *w, bool is_release) {
|
||||||
|
Screen *screen = w->render_data.screen;
|
||||||
|
if (from_button) {
|
||||||
|
if (is_release) screen_update_selection(screen, w->mouse_cell_x, w->mouse_cell_y, true);
|
||||||
|
else screen_start_selection(screen, w->mouse_cell_x, w->mouse_cell_y);
|
||||||
|
} else if (screen->selection.in_progress) {
|
||||||
|
screen_update_selection(screen, w->mouse_cell_x, w->mouse_cell_y, false);
|
||||||
|
call_boss(set_primary_selection, NULL);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
HANDLER(handle_move_event) {
|
HANDLER(handle_move_event) {
|
||||||
unsigned int x, y;
|
unsigned int x, y;
|
||||||
if (cell_for_pos(w, &x, &y)) {
|
if (!cell_for_pos(w, &x, &y)) return;
|
||||||
Line *line = screen_visual_line(w->render_data.screen, y);
|
Line *line = screen_visual_line(w->render_data.screen, y);
|
||||||
has_click_cursor = (line && line_url_start_at(line, x) < line->xnum) ? true : false;
|
has_click_cursor = (line && line_url_start_at(line, x) < line->xnum) ? true : false;
|
||||||
if (x != w->mouse_cell_x || y != w->mouse_cell_y) {
|
if (x == w->mouse_cell_x && y == w->mouse_cell_y) return;
|
||||||
w->mouse_cell_x = x; w->mouse_cell_y = y;
|
w->mouse_cell_x = x; w->mouse_cell_y = y;
|
||||||
|
Screen *screen = w->render_data.screen;
|
||||||
|
bool handle_in_kitty = (
|
||||||
|
(screen->modes.mouse_tracking_mode == ANY_MODE ||
|
||||||
|
(screen->modes.mouse_tracking_mode == MOTION_MODE && button >= 0)) &&
|
||||||
|
!(global_state.is_key_pressed[GLFW_KEY_LEFT_SHIFT] || global_state.is_key_pressed[GLFW_KEY_RIGHT_SHIFT])
|
||||||
|
) ? false : true;
|
||||||
|
if (handle_in_kitty) {
|
||||||
|
if (screen->selection.in_progress && button == GLFW_MOUSE_BUTTON_LEFT) {
|
||||||
|
update_drag(false, w, false);
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
// TODO: Implement this
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -107,7 +130,7 @@ HANDLER(handle_button_event) {
|
|||||||
if (handle_in_kitty) {
|
if (handle_in_kitty) {
|
||||||
switch(button) {
|
switch(button) {
|
||||||
case GLFW_MOUSE_BUTTON_LEFT:
|
case GLFW_MOUSE_BUTTON_LEFT:
|
||||||
// TODO: update_drag
|
update_drag(true, w, is_release);
|
||||||
if (is_release) {
|
if (is_release) {
|
||||||
if (modifiers == (int)OPT(open_url_modifiers)) {
|
if (modifiers == (int)OPT(open_url_modifiers)) {
|
||||||
// TODO: click_url
|
// TODO: click_url
|
||||||
@ -121,12 +144,14 @@ HANDLER(handle_button_event) {
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
// TODO: Implement this
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
HANDLER(handle_event) {
|
HANDLER(handle_event) {
|
||||||
switch(button) {
|
switch(button) {
|
||||||
case -1:
|
case -1:
|
||||||
|
for (int i = 0; i < GLFW_MOUSE_BUTTON_5; i++) { if (global_state.mouse_button_pressed[i]) { button = i; break; } }
|
||||||
handle_move_event(w, button, modifiers, window_idx);
|
handle_move_event(w, button, modifiers, window_idx);
|
||||||
break;
|
break;
|
||||||
case GLFW_MOUSE_BUTTON_LEFT:
|
case GLFW_MOUSE_BUTTON_LEFT:
|
||||||
|
|||||||
@ -4,8 +4,8 @@
|
|||||||
|
|
||||||
from .fast_data_types import (
|
from .fast_data_types import (
|
||||||
GLFW_MOUSE_BUTTON_2, GLFW_MOUSE_BUTTON_3, GLFW_MOD_ALT, GLFW_MOD_CONTROL,
|
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, SGR_PROTOCOL,
|
GLFW_MOD_SHIFT, GLFW_MOUSE_BUTTON_4, GLFW_MOUSE_BUTTON_5,
|
||||||
GLFW_MOUSE_BUTTON_1, URXVT_PROTOCOL, UTF8_PROTOCOL
|
GLFW_MOUSE_BUTTON_1,
|
||||||
)
|
)
|
||||||
|
|
||||||
PRESS, RELEASE, DRAG, MOVE = range(4)
|
PRESS, RELEASE, DRAG, MOVE = range(4)
|
||||||
|
|||||||
@ -1283,16 +1283,6 @@ MODE_GETSET(auto_repeat_enabled, DECARM)
|
|||||||
MODE_GETSET(cursor_visible, DECTCEM)
|
MODE_GETSET(cursor_visible, DECTCEM)
|
||||||
MODE_GETSET(cursor_key_mode, DECCKM)
|
MODE_GETSET(cursor_key_mode, DECCKM)
|
||||||
|
|
||||||
static PyObject*
|
|
||||||
mouse_tracking_mode(Screen *self) {
|
|
||||||
return PyLong_FromUnsignedLong(self->modes.mouse_tracking_mode);
|
|
||||||
}
|
|
||||||
|
|
||||||
static PyObject*
|
|
||||||
mouse_tracking_protocol(Screen *self) {
|
|
||||||
return PyLong_FromUnsignedLong(self->modes.mouse_tracking_protocol);
|
|
||||||
}
|
|
||||||
|
|
||||||
static PyObject*
|
static PyObject*
|
||||||
cursor_up(Screen *self, PyObject *args) {
|
cursor_up(Screen *self, PyObject *args) {
|
||||||
unsigned int count = 1;
|
unsigned int count = 1;
|
||||||
@ -1417,13 +1407,6 @@ scroll(Screen *self, PyObject *args) {
|
|||||||
Py_RETURN_FALSE;
|
Py_RETURN_FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
static PyObject*
|
|
||||||
is_selection_in_progress(Screen *self) {
|
|
||||||
PyObject *ans = self->selection.in_progress ? Py_True : Py_False;
|
|
||||||
Py_INCREF(ans);
|
|
||||||
return ans;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool
|
bool
|
||||||
screen_is_selection_dirty(Screen *self) {
|
screen_is_selection_dirty(Screen *self) {
|
||||||
SelectionBoundary start, end;
|
SelectionBoundary start, end;
|
||||||
@ -1507,8 +1490,6 @@ static PyMethodDef methods[] = {
|
|||||||
MND(change_scrollback_size, METH_VARARGS)
|
MND(change_scrollback_size, METH_VARARGS)
|
||||||
MND(erase_characters, METH_VARARGS)
|
MND(erase_characters, METH_VARARGS)
|
||||||
MND(cursor_up, METH_VARARGS)
|
MND(cursor_up, METH_VARARGS)
|
||||||
MND(mouse_tracking_mode, METH_NOARGS)
|
|
||||||
MND(mouse_tracking_protocol, METH_NOARGS)
|
|
||||||
MND(cursor_up1, METH_VARARGS)
|
MND(cursor_up1, METH_VARARGS)
|
||||||
MND(cursor_down, METH_VARARGS)
|
MND(cursor_down, METH_VARARGS)
|
||||||
MND(cursor_down1, METH_VARARGS)
|
MND(cursor_down1, METH_VARARGS)
|
||||||
@ -1526,7 +1507,6 @@ static PyMethodDef methods[] = {
|
|||||||
MND(resize, METH_VARARGS)
|
MND(resize, METH_VARARGS)
|
||||||
MND(set_margins, METH_VARARGS)
|
MND(set_margins, METH_VARARGS)
|
||||||
MND(text_for_selection, METH_NOARGS)
|
MND(text_for_selection, METH_NOARGS)
|
||||||
MND(is_selection_in_progress, METH_NOARGS)
|
|
||||||
MND(scroll, METH_VARARGS)
|
MND(scroll, METH_VARARGS)
|
||||||
MND(toggle_alt_screen, METH_NOARGS)
|
MND(toggle_alt_screen, METH_NOARGS)
|
||||||
MND(reset_callbacks, METH_NOARGS)
|
MND(reset_callbacks, METH_NOARGS)
|
||||||
|
|||||||
@ -53,6 +53,8 @@ typedef struct {
|
|||||||
Window windows[MAX_CHILDREN];
|
Window windows[MAX_CHILDREN];
|
||||||
} Tab;
|
} Tab;
|
||||||
|
|
||||||
|
#define MAX_KEY_COUNT 512
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
Options opts;
|
Options opts;
|
||||||
|
|
||||||
@ -68,6 +70,7 @@ typedef struct {
|
|||||||
unsigned int cell_width, cell_height;
|
unsigned int cell_width, cell_height;
|
||||||
PyObject *application_title;
|
PyObject *application_title;
|
||||||
PyObject *boss;
|
PyObject *boss;
|
||||||
|
bool is_key_pressed[MAX_KEY_COUNT];
|
||||||
} GlobalState;
|
} GlobalState;
|
||||||
extern GlobalState global_state;
|
extern GlobalState global_state;
|
||||||
|
|
||||||
|
|||||||
@ -16,11 +16,11 @@ from .constants import (
|
|||||||
is_key_pressed, mouse_button_pressed, viewport_size, wakeup
|
is_key_pressed, mouse_button_pressed, viewport_size, wakeup
|
||||||
)
|
)
|
||||||
from .fast_data_types import (
|
from .fast_data_types import (
|
||||||
ANY_MODE, BRACKETED_PASTE_END, BRACKETED_PASTE_START, CELL_PROGRAM,
|
BRACKETED_PASTE_END, BRACKETED_PASTE_START, CELL_PROGRAM,
|
||||||
CURSOR_PROGRAM, GLFW_KEY_DOWN, GLFW_KEY_LEFT_SHIFT, GLFW_KEY_RIGHT_SHIFT,
|
CURSOR_PROGRAM, GLFW_KEY_DOWN, GLFW_KEY_LEFT_SHIFT, GLFW_KEY_RIGHT_SHIFT,
|
||||||
GLFW_KEY_UP, GLFW_MOD_SHIFT, GLFW_MOUSE_BUTTON_1, GLFW_MOUSE_BUTTON_4,
|
GLFW_KEY_UP, GLFW_MOD_SHIFT, GLFW_MOUSE_BUTTON_1, GLFW_MOUSE_BUTTON_4,
|
||||||
GLFW_MOUSE_BUTTON_5, GLFW_MOUSE_BUTTON_MIDDLE, GLFW_PRESS, GLFW_RELEASE,
|
GLFW_MOUSE_BUTTON_5, GLFW_MOUSE_BUTTON_MIDDLE, GLFW_PRESS, GLFW_RELEASE,
|
||||||
MOTION_MODE, SCROLL_FULL, SCROLL_LINE, SCROLL_PAGE, Screen,
|
SCROLL_FULL, SCROLL_LINE, SCROLL_PAGE, Screen,
|
||||||
compile_program, create_cell_vao, glfw_post_empty_event, init_cell_program,
|
compile_program, create_cell_vao, glfw_post_empty_event, init_cell_program,
|
||||||
init_cursor_program, remove_vao, set_window_render_data,
|
init_cursor_program, remove_vao, set_window_render_data,
|
||||||
update_window_title, update_window_visibility
|
update_window_title, update_window_visibility
|
||||||
@ -350,14 +350,15 @@ class Window:
|
|||||||
if mouse_button_pressed[b]:
|
if mouse_button_pressed[b]:
|
||||||
button = b
|
button = b
|
||||||
break
|
break
|
||||||
action = MOVE if button is None else DRAG
|
|
||||||
mode = self.screen.mouse_tracking_mode()
|
mode = self.screen.mouse_tracking_mode()
|
||||||
|
ANY_MODE, MOTION_MODE = 3, 2
|
||||||
send_event = (mode == ANY_MODE or (mode == MOTION_MODE and button is not None)) and not (
|
send_event = (mode == ANY_MODE or (mode == MOTION_MODE and button is not None)) and not (
|
||||||
is_key_pressed[GLFW_KEY_LEFT_SHIFT] or is_key_pressed[GLFW_KEY_RIGHT_SHIFT])
|
is_key_pressed[GLFW_KEY_LEFT_SHIFT] or is_key_pressed[GLFW_KEY_RIGHT_SHIFT])
|
||||||
x, y = max(0, x - self.geometry.left), max(0, y - self.geometry.top)
|
x, y = max(0, x - self.geometry.left), max(0, y - self.geometry.top)
|
||||||
self.last_mouse_cursor_pos = x, y
|
self.last_mouse_cursor_pos = x, y
|
||||||
get_boss().change_mouse_cursor(self.has_url_at(x, y))
|
get_boss().change_mouse_cursor(self.has_url_at(x, y))
|
||||||
if send_event:
|
if send_event:
|
||||||
|
action = MOVE if button is None else DRAG
|
||||||
x, y = self.cell_for_pos(x, y)
|
x, y = self.cell_for_pos(x, y)
|
||||||
if x is not None:
|
if x is not None:
|
||||||
ev = encode_mouse_event(mode, self.screen.mouse_tracking_protocol(),
|
ev = encode_mouse_event(mode, self.screen.mouse_tracking_protocol(),
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user