diff --git a/input.c b/input.c index 33547fcd..5032c748 100644 --- a/input.c +++ b/input.c @@ -312,6 +312,14 @@ wl_pointer_motion(void *data, struct wl_pointer *wl_pointer, term->mouse.col = col; term->mouse.row = row; + if (term->mouse.button != 0) { + /* Update selection */ + term->selection.end = (struct coord){col, term->grid->view + row}; + term_damage_view(term); + if (term->frame_callback == NULL) + grid_render(term); + } + term_mouse_motion( term, term->mouse.button, term->mouse.row, term->mouse.col, term->kbd.shift, term->kbd.alt, term->kbd.ctrl); @@ -327,12 +335,25 @@ wl_pointer_button(void *data, struct wl_pointer *wl_pointer, switch (state) { case WL_POINTER_BUTTON_STATE_PRESSED: + /* Start selection */ + term->selection.start = (struct coord){ + term->mouse.col, term->grid->view + term->mouse.row}; + term->selection.end = (struct coord){-1, -1}; + 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: + if (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); + } + 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); diff --git a/main.c b/main.c index 0b3485bc..888bdae3 100644 --- a/main.c +++ b/main.c @@ -313,6 +313,10 @@ main(int argc, char *const *argv) }, .foreground = default_foreground, .background = default_background, + .selection = { + .start = {-1, -1}, + .end = {-1, -1}, + }, .normal = {.damage = tll_init(), .scroll_damage = tll_init()}, .alt = {.damage = tll_init(), .scroll_damage = tll_init()}, .grid = &term.normal, diff --git a/render.c b/render.c index a97e53cb..b651f99c 100644 --- a/render.c +++ b/render.c @@ -42,6 +42,32 @@ render_cell(struct terminal *term, struct buffer *buf, const struct cell *cell, double x = col * width; double y = row * height; + bool is_selected = false; + if (term->selection.start.col != -1 && term->selection.end.col != -1) { + const struct coord *start = &term->selection.start; + const struct coord *end = &term->selection.end; + + if (end->row < start->row || (end->row == start->row && end->col < start->col)) { + const struct coord *tmp = start; + start = end; + end = tmp; + } + + assert(start->row <= end->row); + + if (start->row == end->row) { + is_selected + = term->grid->view + row == start->row && col >= start->col && col <= end->col; + } else { + if (term->grid->view + row == start->row) + is_selected = col >= start->col; + else if (term->grid->view + row == end->row) + is_selected = col <= end->col; + else + is_selected = term->grid->view + row >= start->row && term->grid->view + row <= end->row; + } + } + const struct rgb *foreground = cell->attrs.have_foreground ? &cell->attrs.foreground : !term->reverse ? &term->foreground : &term->background; @@ -50,7 +76,7 @@ render_cell(struct terminal *term, struct buffer *buf, const struct cell *cell, : !term->reverse ? &term->background : &term->foreground; /* If *one* is set, we reverse */ - if (has_cursor ^ cell->attrs.reverse) { + if (has_cursor ^ cell->attrs.reverse ^ is_selected) { const struct rgb *swap = foreground; foreground = background; background = swap; diff --git a/terminal.h b/terminal.h index fdb86a81..1e56567f 100644 --- a/terminal.h +++ b/terminal.h @@ -228,6 +228,11 @@ struct terminal { struct coord saved_cursor; struct coord alt_saved_cursor; + struct { + struct coord start; + struct coord end; + } selection; + struct grid normal; struct grid alt; struct grid *grid;