diff --git a/csi.c b/csi.c index 67d78720..cf586bd1 100644 --- a/csi.c +++ b/csi.c @@ -597,28 +597,26 @@ csi_dispatch(struct terminal *term, uint8_t final) break; case 1002: - LOG_WARN("unimplemented: report button and mouse motion"); - /* term->mouse_tracking = MOUSE_DRAG; */ + term->mouse_tracking = MOUSE_DRAG; break; case 1003: - LOG_WARN("unimplemented: report all mouse events"); - /* term->mouse_tracking = MOUSE_MOTION; */ + term->mouse_tracking = MOUSE_MOTION; break; case 1005: LOG_WARN("unimplemented: UTF-8 mouse"); - /* term->mouse_reporting = MOUSE_UTF8 */ + /* term->mouse_reporting = MOUSE_UTF8; */ break; case 1006: LOG_WARN("unimplemented: SGR mouse"); - /* term->mouse_reporting = MOUSE_SGR */ + term->mouse_reporting = MOUSE_SGR; break; case 1015: LOG_WARN("unimplemented: URXVT mosue"); - /* term->mouse_reporting = MOUSE_URXVT */ + /* term->mouse_reporting = MOUSE_URXVT; */ break; case 1049: diff --git a/input.c b/input.c index 36e9096c..4027d801 100644 --- a/input.c +++ b/input.c @@ -33,6 +33,10 @@ keyboard_keymap(void *data, struct wl_keyboard *wl_keyboard, /* TODO: initialize in enter? */ term->kbd.xkb_state = xkb_state_new(term->kbd.xkb_keymap); + term->kbd.mod_shift = xkb_keymap_mod_get_index(term->kbd.xkb_keymap, "Shift"); + term->kbd.mod_alt = xkb_keymap_mod_get_index(term->kbd.xkb_keymap, "Mod1") ; + term->kbd.mod_ctrl = xkb_keymap_mod_get_index(term->kbd.xkb_keymap, "Control"); + munmap(map_str, size); close(fd); } @@ -147,19 +151,11 @@ static void keyboard_key(void *data, struct wl_keyboard *wl_keyboard, uint32_t serial, uint32_t time, uint32_t key, uint32_t state) { - static bool mod_masks_initialized = false; - static xkb_mod_mask_t ctrl = -1; - static xkb_mod_mask_t alt = -1; - static xkb_mod_mask_t shift = -1; - struct terminal *term = data; - if (!mod_masks_initialized) { - mod_masks_initialized = true; - ctrl = 1 << xkb_keymap_mod_get_index(term->kbd.xkb_keymap, "Control"); - alt = 1 << xkb_keymap_mod_get_index(term->kbd.xkb_keymap, "Mod1"); - shift = 1 << xkb_keymap_mod_get_index(term->kbd.xkb_keymap, "Shift"); - } + const xkb_mod_mask_t ctrl = 1 << term->kbd.mod_ctrl; + const xkb_mod_mask_t alt = 1 << term->kbd.mod_alt; + const xkb_mod_mask_t shift = 1 << term->kbd.mod_shift; if (state == XKB_KEY_UP) { mtx_lock(&term->kbd.repeat.mutex); @@ -262,6 +258,14 @@ keyboard_modifiers(void *data, struct wl_keyboard *wl_keyboard, uint32_t serial, xkb_state_update_mask( term->kbd.xkb_state, mods_depressed, mods_latched, mods_locked, 0, 0, group); + + /* Update state of modifiers we're interrested in for e.g mouse events */ + term->kbd.shift = xkb_state_mod_index_is_active( + term->kbd.xkb_state, term->kbd.mod_shift, XKB_STATE_MODS_DEPRESSED); + term->kbd.alt = xkb_state_mod_index_is_active( + term->kbd.xkb_state, term->kbd.mod_alt, XKB_STATE_MODS_DEPRESSED); + term->kbd.ctrl = xkb_state_mod_index_is_active( + term->kbd.xkb_state, term->kbd.mod_ctrl, XKB_STATE_MODS_DEPRESSED); } static void @@ -295,8 +299,12 @@ wl_pointer_enter(void *data, struct wl_pointer *wl_pointer, wl_fixed_t surface_x, wl_fixed_t surface_y) { struct terminal *term = data; - term->mouse.x = wl_fixed_to_int(surface_x); - term->mouse.y = wl_fixed_to_int(surface_y); + + int x = wl_fixed_to_int(surface_x) * 1; //scale + int y = wl_fixed_to_int(surface_y) * 1; //scale + + term->mouse.col = x / term->cell_width; + term->mouse.row = y / term->cell_height; render_update_cursor_surface(term); } @@ -312,8 +320,22 @@ wl_pointer_motion(void *data, struct wl_pointer *wl_pointer, uint32_t time, wl_fixed_t surface_x, wl_fixed_t surface_y) { struct terminal *term = data; - term->mouse.x = wl_fixed_to_int(surface_x) * 1;//backend->monitor->scale; - term->mouse.y = wl_fixed_to_int(surface_y) * 1;//backend->monitor->scale; + + int x = wl_fixed_to_int(surface_x) * 1;//backend->monitor->scale; + int y = wl_fixed_to_int(surface_y) * 1;//backend->monitor->scale; + + int col = x / term->cell_width; + int row = y / term->cell_width; + + if (col == term->mouse.col && row == term->mouse.row) + return; + + term->mouse.col = x / term->cell_width; + term->mouse.row = y / term->cell_height; + + term_mouse_motion( + term, term->mouse.button, term->mouse.row, term->mouse.col, + term->kbd.shift, term->kbd.alt, term->kbd.ctrl); } static void @@ -324,35 +346,17 @@ wl_pointer_button(void *data, struct wl_pointer *wl_pointer, struct terminal *term = data; - static bool mods_initialized = false; - static xkb_mod_index_t shift, alt, ctrl; - - if (!mods_initialized) { - struct xkb_keymap *map = term->kbd.xkb_keymap; - shift = xkb_keymap_mod_get_index(map, "Shift"); - alt = xkb_keymap_mod_get_index(map, "Mod1") ; - ctrl = xkb_keymap_mod_get_index(map, "Control"); - mods_initialized = true; - } - - int col = term->mouse.x / term->cell_width; - int row = term->mouse.y / term->cell_height; - - struct xkb_state *xkb = term->kbd.xkb_state; - bool shift_active = xkb_state_mod_index_is_active( - xkb, shift, XKB_STATE_MODS_DEPRESSED); - bool alt_active = xkb_state_mod_index_is_active( - xkb, alt, XKB_STATE_MODS_DEPRESSED); - bool ctrl_active = xkb_state_mod_index_is_active( - xkb, ctrl, XKB_STATE_MODS_DEPRESSED); - switch (state) { case WL_POINTER_BUTTON_STATE_PRESSED: - term_mouse_down(term, button, row, col, shift_active, alt_active, ctrl_active); + term->mouse.button = button; /* For motion events */ + term_mouse_down(term, button, term->mouse.row, term->mouse.col, + term->kbd.shift, term->kbd.alt, term->kbd.ctrl); break; case WL_POINTER_BUTTON_STATE_RELEASED: - term_mouse_up(term, button, row, col, shift_active, alt_active, ctrl_active); + term->mouse.button = 0; /* For motion events */ + term_mouse_up(term, button, term->mouse.row, term->mouse.col, + term->kbd.shift, term->kbd.alt, term->kbd.ctrl); break; } } diff --git a/terminal.c b/terminal.c index 37cb9bbd..7639da2d 100644 --- a/terminal.c +++ b/terminal.c @@ -423,35 +423,36 @@ encode_xbutton(int xbutton) } static void -report_mouse_click(struct terminal *term, int button, int row, int col, - bool release, bool shift, bool alt, bool ctrl) +report_mouse_click(struct terminal *term, int encoded_button, int row, int col, + bool release) { - /* Map libevent button event code to X button number */ - int xbutton = linux_mouse_button_to_x(button); - if (xbutton == -1) - return; - - if (release && (xbutton == 4 || xbutton == 5)) { - /* No button release events for scroll buttons */ - return; - } - - int encoded = release ? 3 : encode_xbutton(xbutton); - if (encoded == -1) - return; - - encoded += (shift ? 4 : 0) + (alt ? 8 : 0) + (ctrl ? 16 : 0); - char response[16]; snprintf(response, sizeof(response), "\033[M%c%c%c", - 32 + encoded, 32 + col + 1, 32 + row + 1); + 32 + encoded_button, 32 + col + 1, 32 + row + 1); write(term->ptmx, response, strlen(response)); } +static void +report_mouse_motion(struct terminal *term, int encoded_button, int row, int col) +{ + report_mouse_click(term, encoded_button, row, col, false); +} + void term_mouse_down(struct terminal *term, int button, int row, int col, bool shift, bool alt, bool ctrl) { + /* Map libevent button event code to X button number */ + int xbutton = linux_mouse_button_to_x(button); + if (xbutton == -1) + return; + + int encoded = encode_xbutton(xbutton); + if (encoded == -1) + return; + + encoded += (shift ? 4 : 0) + (alt ? 8 : 0) + (ctrl ? 16 : 0); + switch (term->mouse_tracking) { case MOUSE_NONE: break; @@ -460,7 +461,7 @@ term_mouse_down(struct terminal *term, int button, int row, int col, case MOUSE_CLICK: case MOUSE_DRAG: case MOUSE_MOTION: - report_mouse_click(term, button, row, col, false, shift, alt, ctrl); + report_mouse_click(term, encoded, row, col, false); break; } } @@ -469,6 +470,19 @@ void term_mouse_up(struct terminal *term, int button, int row, int col, bool shift, bool alt, bool ctrl) { + /* Map libevent button event code to X button number */ + int xbutton = linux_mouse_button_to_x(button); + if (xbutton == -1) + return; + + if (xbutton == 4 || xbutton == 5) { + /* No release events for scroll buttons */ + return; + } + + int encoded = 3; + encoded += (shift ? 4 : 0) + (alt ? 8 : 0) + (ctrl ? 16 : 0); + switch (term->mouse_tracking) { case MOUSE_NONE: break; @@ -477,7 +491,45 @@ term_mouse_up(struct terminal *term, int button, int row, int col, case MOUSE_CLICK: case MOUSE_DRAG: case MOUSE_MOTION: - report_mouse_click(term, button, row, col, true, shift, alt, ctrl); + report_mouse_click(term, encoded, row, col, true); + break; + } +} + +void +term_mouse_motion(struct terminal *term, int button, int row, int col, + bool shift, bool alt, bool ctrl) +{ + int encoded = 0; + + if (button != 0) { + /* Map libevent button event code to X button number */ + int xbutton = linux_mouse_button_to_x(button); + if (xbutton == -1) + return; + + encoded = encode_xbutton(xbutton); + if (encoded == -1) + return; + } else + encoded = 3; /* "released" */ + + encoded += 32; /* Motion event */ + encoded += (shift ? 4 : 0) + (alt ? 8 : 0) + (ctrl ? 16 : 0); + + switch (term->mouse_tracking) { + case MOUSE_NONE: + case MOUSE_X10: + case MOUSE_CLICK: + return; + + case MOUSE_DRAG: + if (button == 0) + return; + /* FALLTHROUGH */ + + case MOUSE_MOTION: + report_mouse_motion(term, encoded, row, col); break; } } diff --git a/terminal.h b/terminal.h index 2aa8699e..4642bbae 100644 --- a/terminal.h +++ b/terminal.h @@ -145,6 +145,15 @@ struct kbd { int32_t rate; uint32_t key; } repeat; + + xkb_mod_index_t mod_shift; + xkb_mod_index_t mod_alt; + xkb_mod_index_t mod_ctrl; + + /* Enabled modifiers */ + bool shift; + bool alt; + bool ctrl; }; enum decckm { DECCKM_CSI, DECCKM_SS3 }; @@ -202,8 +211,9 @@ struct terminal { struct rgba background; struct { - int x; - int y; + int row; + int col; + int button; } mouse; struct cursor cursor; @@ -250,3 +260,5 @@ void term_mouse_down(struct terminal *term, int button, int row, int col, bool shift, bool alt, bool ctrl); void term_mouse_up(struct terminal *term, int button, int row, int col, bool shift, bool alt, bool ctrl); +void term_mouse_motion(struct terminal *term, int button, int row, int col, + bool shift, bool alt, bool ctrl);