From bcf763d41776705ad62972e766d73fd9533bbb9e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Ekl=C3=B6f?= Date: Thu, 11 Jul 2019 09:51:51 +0200 Subject: [PATCH] selection: add a selection API --- input.c | 45 +++++++++++++--------------------- meson.build | 1 + selection.c | 70 +++++++++++++++++++++++++++++++++++++++++++++++++++++ selection.h | 8 ++++++ terminal.c | 19 +++++++++++++-- terminal.h | 4 +++ 6 files changed, 117 insertions(+), 30 deletions(-) create mode 100644 selection.c create mode 100644 selection.h diff --git a/input.c b/input.c index a6369a51..e075bf4b 100644 --- a/input.c +++ b/input.c @@ -20,6 +20,7 @@ #include "render.h" #include "keymap.h" #include "commands.h" +#include "selection.h" static void keyboard_keymap(void *data, struct wl_keyboard *wl_keyboard, @@ -178,10 +179,10 @@ keyboard_key(void *data, struct wl_keyboard *wl_keyboard, uint32_t serial, if (term->grid->view != term->grid->offset) { term->grid->view = term->grid->offset; - /* TODO: damage view */ term_damage_all(term); } + selection_cancel(term); break; } } @@ -207,10 +208,10 @@ keyboard_key(void *data, struct wl_keyboard *wl_keyboard, uint32_t serial, if (term->grid->view != term->grid->offset) { term->grid->view = term->grid->offset; - /* TODO: damage view */ term_damage_all(term); } + selection_cancel(term); } } @@ -306,19 +307,20 @@ wl_pointer_motion(void *data, struct wl_pointer *wl_pointer, int col = x / term->cell_width; int row = y / term->cell_height; + bool update_selection = term->mouse.button == BTN_LEFT; + bool update_selection_early = term->selection.end.row == -1; + + if (update_selection && update_selection_early) + selection_update(term, col, row); + if (col == term->mouse.col && row == term->mouse.row) return; term->mouse.col = col; term->mouse.row = row; - if (term->mouse.button == BTN_LEFT) { - /* Update selection */ - term->selection.end = (struct coord){col, term->grid->view + row}; - term_damage_view(term); - if (term->frame_callback == NULL) - grid_render(term); - } + if (update_selection && !update_selection_early) + selection_update(term, col, row); term_mouse_motion( term, term->mouse.button, term->mouse.row, term->mouse.col, @@ -335,18 +337,10 @@ wl_pointer_button(void *data, struct wl_pointer *wl_pointer, switch (state) { case WL_POINTER_BUTTON_STATE_PRESSED: - if (button == BTN_LEFT) { - /* Start selection */ - term->selection.start = (struct coord){ - term->mouse.col, term->grid->view + term->mouse.row}; - term->selection.end = (struct coord){-1, -1}; - } else { - term->selection.start = (struct coord){-1, -1}; - term->selection.end = (struct coord){-1, -1}; - term_damage_view(term); - if (term->frame_callback == NULL) - grid_render(term); - } + if (button == BTN_LEFT) + selection_start(term, term->mouse.col, term->mouse.row); + else + selection_cancel(term); term->mouse.button = button; /* For motion events */ term_mouse_down(term, button, term->mouse.row, term->mouse.col, @@ -354,13 +348,8 @@ wl_pointer_button(void *data, struct wl_pointer *wl_pointer, break; case WL_POINTER_BUTTON_STATE_RELEASED: - if (button == BTN_LEFT && term->selection.end.col == -1) { - /* No selection made - cancel */ - term->selection.start = (struct coord){-1, -1}; - term_damage_view(term); - if (term->frame_callback == NULL) - grid_render(term); - } + if (button == BTN_LEFT && term->selection.end.col == -1) + selection_cancel(term); term->mouse.button = 0; /* For motion events */ term_mouse_up(term, button, term->mouse.row, term->mouse.col, diff --git a/meson.build b/meson.build index 7cb057bf..51ee526f 100644 --- a/meson.build +++ b/meson.build @@ -67,6 +67,7 @@ executable( 'main.c', 'osc.c', 'osc.h', 'render.c', 'render.h', + 'selection.c', 'selection.h', 'shm.c', 'shm.h', 'slave.c', 'slave.h', 'terminal.c', 'terminal.h', diff --git a/selection.c b/selection.c new file mode 100644 index 00000000..b0b688b9 --- /dev/null +++ b/selection.c @@ -0,0 +1,70 @@ +#include "selection.h" + +#define LOG_MODULE "selection" +#define LOG_ENABLE_DBG 1 +#include "log.h" +#include "render.h" + +#define min(x, y) ((x) < (y) ? (x) : (y)) +#define max(x, y) ((x) > (y) ? (x) : (y)) + +void +selection_start(struct terminal *term, int col, int row) +{ + selection_cancel(term); + + LOG_DBG("selection started at %d,%d", row, col); + term->selection.start = (struct coord){col, row}; + term->selection.end = (struct coord){-1, -1}; +} + +void +selection_update(struct terminal *term, int col, int row) +{ + LOG_DBG("selection updated: start = %d,%d, end = %d,%d -> %d, %d", + term->selection.start.row, term->selection.start.col, + term->selection.end.row, term->selection.end.col, + row, col); + + term->selection.end = (struct coord){col, term->grid->view + row}; + + assert(term->selection.start.row != -1 && term->selection.end.row != -1); + term_damage_rows_in_view( + term, + min(term->selection.start.row, term->selection.end.row) - term->grid->view, + max(term->selection.start.row, term->selection.end.row) - term->grid->view); + + if (term->frame_callback == NULL) + grid_render(term); +} + +void +selection_finalizie(struct terminal *term) +{ + assert(term->selection.start.row != -1); + assert(term->selection.end.row != -1); +} + +void +selection_cancel(struct terminal *term) +{ + LOG_DBG("selection cancelled: start = %d,%d end = %d,%d", + term->selection.start.row, term->selection.start.col, + term->selection.end.row, term->selection.end.col); + + int start_row = term->selection.start.row; + int end_row = term->selection.end.row; + + term->selection.start = (struct coord){-1, -1}; + term->selection.end = (struct coord){-1, -1}; + + if (start_row != -1 && end_row != -1) { + term_damage_rows_in_view( + term, + min(start_row, end_row) - term->grid->view, + max(start_row, end_row) - term->grid->view); + + if (term->frame_callback == NULL) + grid_render(term); + } +} diff --git a/selection.h b/selection.h new file mode 100644 index 00000000..96b8b489 --- /dev/null +++ b/selection.h @@ -0,0 +1,8 @@ +#pragma once + +#include "terminal.h" + +void selection_start(struct terminal *term, int col, int row); +void selection_update(struct terminal *term, int col, int row); +void selection_finalizie(struct terminal *term); +void selection_cancel(struct terminal *term); diff --git a/terminal.c b/terminal.c index 5b4b0f50..d6d75641 100644 --- a/terminal.c +++ b/terminal.c @@ -14,11 +14,26 @@ #define min(x, y) ((x) < (y) ? (x) : (y)) #define max(x, y) ((x) > (y) ? (x) : (y)) +void +term_damage_rows(struct terminal *term, int start, int end) +{ + assert(start <= end); + for (int r = start; r <= end; r++) + grid_row(term->grid, r)->dirty = true; +} + +void +term_damage_rows_in_view(struct terminal *term, int start, int end) +{ + assert(start <= end); + for (int r = start; r <= end; r++) + grid_row_in_view(term->grid, r)->dirty = true; +} + void term_damage_all(struct terminal *term) { - for (int i = 0; i < term->rows; i++) - grid_row(term->grid, i)->dirty = true; + term_damage_rows(term, 0, term->rows); } void diff --git a/terminal.h b/terminal.h index 1e56567f..8b080ad9 100644 --- a/terminal.h +++ b/terminal.h @@ -244,8 +244,12 @@ struct terminal { struct wl_callback *frame_callback; }; +void term_damage_rows(struct terminal *term, int start, int end); +void term_damage_rows_in_view(struct terminal *term, int start, int end); + void term_damage_all(struct terminal *term); void term_damage_view(struct terminal *term); + void term_damage_scroll( struct terminal *term, enum damage_type damage_type, struct scroll_region region, int lines);