diff --git a/config.c b/config.c index 8e51b608..69883b68 100644 --- a/config.c +++ b/config.c @@ -69,6 +69,12 @@ static const char *const binding_action_map[] = { [BIND_ACTION_PIPE_SCROLLBACK] = "pipe-scrollback", [BIND_ACTION_PIPE_VIEW] = "pipe-visible", [BIND_ACTION_PIPE_SELECTED] = "pipe-selected", + + /* Mouse-specific actions */ + [BIND_ACTION_SELECT_BEGIN] = "select-begin", + [BIND_ACTION_SELECT_WORD] = "select-word", + [BIND_ACTION_SELECT_WORD_WS] = "select-word-whitespace", + [BIND_ACTION_SELECT_EXTEND] = "select-extend", }; static_assert(ALEN(binding_action_map) == BIND_ACTION_COUNT, @@ -643,7 +649,8 @@ parse_section_csd(const char *key, const char *value, struct config *conf, } else { - LOG_AND_NOTIFY_ERR("%s:%u: [csd]: %s: invalid key", path, lineno, key); + LOG_AND_NOTIFY_ERR("%s:%u: [csd]: %s: invalid action", + path, lineno, key); return false; } @@ -859,7 +866,7 @@ parse_section_key_bindings( } for (enum bind_action_normal action = 0; - action < BIND_ACTION_COUNT; + action < BIND_ACTION_KEY_COUNT; action++) { if (binding_action_map[action] == NULL) @@ -932,7 +939,8 @@ parse_section_key_bindings( return true; } - LOG_AND_NOTIFY_ERR("%s:%u: [key-bindings]: %s: invalid key", path, lineno, key); + LOG_AND_NOTIFY_ERR("%s:%u: [key-bindings]: %s: invalid action", + path, lineno, key); return false; } @@ -1121,7 +1129,10 @@ parse_section_mouse_bindings( const char *key, const char *value, struct config *conf, const char *path, unsigned lineno) { - for (enum bind_action_normal action = 0; action < BIND_ACTION_COUNT; action++) { + for (enum bind_action_normal action = 0; + action < BIND_ACTION_COUNT; + action++) + { if (binding_action_map[action] == NULL) continue; @@ -1519,8 +1530,13 @@ add_default_mouse_bindings(struct config *conf) } while (0) const struct config_key_modifiers none = {}; + const struct config_key_modifiers ctrl = {.ctrl = true}; add_binding(BIND_ACTION_PRIMARY_PASTE, none, BTN_MIDDLE, 1); + add_binding(BIND_ACTION_SELECT_BEGIN, none, BTN_LEFT, 1); + add_binding(BIND_ACTION_SELECT_WORD, none, BTN_LEFT, 2); + add_binding(BIND_ACTION_SELECT_WORD_WS, ctrl, BTN_LEFT, 2); + add_binding(BIND_ACTION_SELECT_EXTEND, none, BTN_RIGHT, 1); #undef add_binding } diff --git a/footrc b/footrc index ec36bbc1..062b9177 100644 --- a/footrc +++ b/footrc @@ -93,3 +93,7 @@ [mouse-bindings] # primary-paste=BTN_MIDDLE +# select-begin=BTN_LEFT +# select-word=BTN_LEFT-2 +# select-word-whitespace=Control+BTN_LEFT-2 +# select-extend=BTN_RIGHT diff --git a/input.c b/input.c index b7c5031a..9e260e69 100644 --- a/input.c +++ b/input.c @@ -254,6 +254,31 @@ execute_binding(struct seat *seat, struct terminal *term, break; } + case BIND_ACTION_SELECT_BEGIN: + selection_start( + term, seat->mouse.col, seat->mouse.row, + seat->kbd.ctrl ? SELECTION_BLOCK : SELECTION_NORMAL); + break; + + case BIND_ACTION_SELECT_WORD: + selection_mark_word( + seat, term, seat->mouse.col, seat->mouse.row, false, serial); + break; + + case BIND_ACTION_SELECT_WORD_WS: + selection_mark_word( + seat, term, seat->mouse.col, seat->mouse.row, true, serial); + break; + + case BIND_ACTION_SELECT_EXTEND: { + bool cursor_is_on_grid = seat->mouse.col >= 0 && seat->mouse.row >= 0; + if (selection_enabled(term, seat) && cursor_is_on_grid) { + selection_extend( + seat, term, seat->mouse.col, seat->mouse.row, serial); + } + break; + } + case BIND_ACTION_COUNT: assert(false); break; @@ -1442,38 +1467,7 @@ wl_pointer_button(void *data, struct wl_pointer *wl_pointer, switch (state) { case WL_POINTER_BUTTON_STATE_PRESSED: { - if (button == BTN_LEFT && seat->mouse.count <= 3 && mods == 0) { - selection_cancel(term); - - if (selection_enabled(term, seat) && cursor_is_on_grid) { - switch (seat->mouse.count) { - case 1: - selection_start( - term, seat->mouse.col, seat->mouse.row, - seat->kbd.ctrl ? SELECTION_BLOCK : SELECTION_NORMAL); - break; - - case 2: - selection_mark_word( - seat, term, seat->mouse.col, seat->mouse.row, - seat->kbd.ctrl, serial); - break; - - case 3: - selection_mark_row(seat, term, seat->mouse.row, serial); - break; - } - } - } - - else if (button == BTN_RIGHT && seat->mouse.count == 1 && mods == 0) { - if (selection_enabled(term, seat) && cursor_is_on_grid) { - selection_extend( - seat, term, seat->mouse.col, seat->mouse.row, serial); - } - } - - else if (seat->wl_keyboard != NULL) { + if (seat->wl_keyboard != NULL) { /* Seat has keyboard - use mouse bindings *with* modifiers */ tll_foreach(seat->mouse.bindings, it) { const struct mouse_binding *binding = &it->item; @@ -1533,8 +1527,7 @@ wl_pointer_button(void *data, struct wl_pointer *wl_pointer, } case WL_POINTER_BUTTON_STATE_RELEASED: - if (button == BTN_LEFT && term->selection.end.col != -1) - selection_finalize(seat, term, serial); + selection_finalize(seat, term, serial); if (!term_mouse_grabbed(term, seat) && cursor_is_on_grid) { term_mouse_up( diff --git a/selection.c b/selection.c index a078a698..3eadf2ea 100644 --- a/selection.c +++ b/selection.c @@ -237,6 +237,7 @@ selection_start(struct terminal *term, int col, int row, term->selection.kind = kind; term->selection.start = (struct coord){col, term->grid->view + row}; term->selection.end = (struct coord){-1, -1}; + term->selection.ongoing = true; } static bool @@ -566,6 +567,11 @@ selection_finalize(struct seat *seat, struct terminal *term, uint32_t serial) if (term->selection.start.row < 0 || term->selection.end.row < 0) return; + if (!term->selection.ongoing) + return; + + term->selection.ongoing = false; + assert(term->selection.start.row != -1); assert(term->selection.end.row != -1); @@ -600,6 +606,7 @@ selection_cancel(struct terminal *term) term->selection.start = (struct coord){-1, -1}; term->selection.end = (struct coord){-1, -1}; term->selection.direction = SELECTION_UNDIR; + term->selection.ongoing = false; } void diff --git a/terminal.h b/terminal.h index 8509634a..2f2d8881 100644 --- a/terminal.h +++ b/terminal.h @@ -311,6 +311,7 @@ struct terminal { enum selection_direction direction; struct coord start; struct coord end; + bool ongoing; } selection; bool is_searching; diff --git a/wayland.h b/wayland.h index b08c25fd..b7528a7f 100644 --- a/wayland.h +++ b/wayland.h @@ -42,6 +42,15 @@ enum bind_action_normal { BIND_ACTION_PIPE_SCROLLBACK, BIND_ACTION_PIPE_VIEW, BIND_ACTION_PIPE_SELECTED, + + BIND_ACTION_KEY_COUNT = BIND_ACTION_PIPE_SELECTED, + + /* Mouse specific actions - i.e. they require a mouse coordinate */ + BIND_ACTION_SELECT_BEGIN, + BIND_ACTION_SELECT_WORD, + BIND_ACTION_SELECT_WORD_WS, + BIND_ACTION_SELECT_EXTEND, + BIND_ACTION_COUNT, };