From 8eb5a8256d3ff98d3b3f623e05164388cdcbd93c Mon Sep 17 00:00:00 2001 From: Some Chinese Guy Date: Sun, 12 Apr 2020 02:35:21 +0300 Subject: [PATCH] separated pointer and touch selection states --- include/slurp.h | 15 ++++++- main.c | 115 +++++++++++++++++++++++++++++++++--------------- render.c | 47 ++++++++++++-------- 3 files changed, 122 insertions(+), 55 deletions(-) diff --git a/include/slurp.h b/include/slurp.h index 1f5db66..ebf5e75 100644 --- a/include/slurp.h +++ b/include/slurp.h @@ -17,6 +17,14 @@ struct slurp_box { struct wl_list link; }; +struct slurp_selection { + struct slurp_output *current_output; + int32_t x, y; + int32_t anchor_x, anchor_y; + struct slurp_box selection; + bool has_selection; +}; + struct slurp_state { bool running; bool edit_anchor; @@ -81,11 +89,13 @@ struct slurp_seat { struct wl_keyboard *wl_keyboard; //selection (pointer/touch): - struct slurp_output *current_output; + /*struct slurp_output *current_output; int32_t x, y; int32_t anchor_x, anchor_y; struct slurp_box selection; - bool has_selection; + bool has_selection;*/ + struct slurp_selection pointer_selection; + struct slurp_selection touch_selection; // pointer: struct wl_pointer *wl_pointer; @@ -101,4 +111,5 @@ struct slurp_seat { }; bool box_intersect(const struct slurp_box *a, const struct slurp_box *b); +struct slurp_selection* seat_get_current_selection(struct slurp_seat* seat); #endif diff --git a/main.c b/main.c index 4b79505..019292d 100644 --- a/main.c +++ b/main.c @@ -26,21 +26,37 @@ bool box_intersect(const struct slurp_box *a, const struct slurp_box *b) { a->height + a->y > b->y; } +struct slurp_selection *seat_get_current_selection(struct slurp_seat *seat) { + if (seat->pointer_selection.has_selection) { + return &seat->pointer_selection; + } else if (seat->touch_selection.has_selection) { + return &seat->touch_selection; + } else { + return NULL; + } +} + static struct slurp_output *output_from_surface(struct slurp_state *state, struct wl_surface *surface); static void move_seat(struct slurp_seat *seat, wl_fixed_t surface_x, wl_fixed_t surface_y) { - int x = wl_fixed_to_int(surface_x) + seat->current_output->logical_geometry.x; - int y = wl_fixed_to_int(surface_y) + seat->current_output->logical_geometry.y; + struct slurp_selection *current_selection = + seat_get_current_selection(seat); + if (current_selection == NULL) { + //return; + current_selection = &seat->pointer_selection; //still need to track the mouse coordinates; + } + int x = wl_fixed_to_int(surface_x) + current_selection->current_output->logical_geometry.x; + int y = wl_fixed_to_int(surface_y) + current_selection->current_output->logical_geometry.y; if (seat->state->edit_anchor) { - seat->anchor_x += x - seat->x; - seat->anchor_y += y - seat->y; + current_selection->anchor_x += x - current_selection->x; + current_selection->anchor_y += y - current_selection->y; } - seat->x = x; - seat->y = y; + current_selection->x = x; + current_selection->y = y; } static void pointer_handle_enter(void *data, struct wl_pointer *wl_pointer, @@ -52,7 +68,7 @@ static void pointer_handle_enter(void *data, struct wl_pointer *wl_pointer, return; } // TODO: handle multiple overlapping outputs - seat->current_output = output; + seat->pointer_selection.current_output = output; move_seat(seat, surface_x, surface_y); @@ -70,13 +86,16 @@ static void pointer_handle_leave(void *data, struct wl_pointer *wl_pointer, struct slurp_seat *seat = data; // TODO: handle multiple overlapping outputs - seat->current_output = NULL; + seat->pointer_selection.current_output = NULL; } static void seat_set_outputs_dirty(struct slurp_seat *seat) { struct slurp_output *output; wl_list_for_each(output, &seat->state->outputs, link) { - if (box_intersect(&output->logical_geometry, &seat->selection)) { + if (box_intersect(&output->logical_geometry, + &seat->pointer_selection.selection) || + box_intersect(&output->logical_geometry, + &seat->touch_selection.selection)) { set_output_dirty(output); } } @@ -102,21 +121,28 @@ static int max(int a, int b) { } static void handle_active_selection_motion(struct slurp_seat *seat) { - int32_t anchor_x = max(0, seat->anchor_x); - int32_t anchor_y = max(0, seat->anchor_y); - seat->has_selection = true; - seat->selection.x = min(anchor_x, seat->x); - seat->selection.y = min(anchor_y, seat->y); + struct slurp_selection *current_selection = + seat_get_current_selection(seat); + if (current_selection == NULL) { + return; + } + int32_t anchor_x = max(0, current_selection->anchor_x); + int32_t anchor_y = max(0, current_selection->anchor_y); + //current_selection->has_selection = true; + current_selection->selection.x = min(anchor_x, current_selection->x); + current_selection->selection.y = min(anchor_y, current_selection->y); // selection includes the seat and anchor positions - seat->selection.width = abs(seat->x - anchor_x) + 1; - seat->selection.height = abs(seat->y - anchor_y) + 1; + current_selection->selection.width = + abs(current_selection->x - anchor_x) + 1; + current_selection->selection.height = + abs(current_selection->y - anchor_y) + 1; } static void pointer_handle_motion(void *data, struct wl_pointer *wl_pointer, uint32_t time, wl_fixed_t surface_x, wl_fixed_t surface_y) { struct slurp_seat *seat = data; // the places the cursor moved away from are also dirty - if (seat->has_selection) { + if (seat->pointer_selection.has_selection) { seat_set_outputs_dirty(seat); } @@ -124,18 +150,22 @@ static void pointer_handle_motion(void *data, struct wl_pointer *wl_pointer, switch (seat->button_state) { case WL_POINTER_BUTTON_STATE_RELEASED: - seat->has_selection = false; + seat->pointer_selection.has_selection = false; // find smallest box intersecting the cursor struct slurp_box *box; - wl_list_for_each(box, &seat->state->boxes, link) { - if (in_box(box, seat->x, seat->y)) { - if (seat->has_selection && - box_size(&seat->selection) < box_size(box)) { + wl_list_for_each(box, &seat->state->boxes, link) + { + if (in_box(box, seat->pointer_selection.x, + seat->pointer_selection.y)) { + if (seat->pointer_selection.has_selection && + box_size( + &seat->pointer_selection.selection) < + box_size(box)) { continue; } - seat->selection = *box; - seat->has_selection = true; + seat->pointer_selection.selection = *box; + seat->pointer_selection.has_selection = true; } } break; @@ -144,31 +174,36 @@ static void pointer_handle_motion(void *data, struct wl_pointer *wl_pointer, break; } - if (seat->has_selection) { + if (seat->pointer_selection.has_selection) { seat_set_outputs_dirty(seat); } } static void handle_selection_start(struct slurp_seat *seat) { struct slurp_state *state = seat->state; + struct slurp_selection *current_selection = seat_get_current_selection(seat); + if (current_selection == NULL) { + return; + } if (state->single_point) { - state->result.x = seat->x; - state->result.y = seat->y; + state->result.x = current_selection->x; + state->result.y = current_selection->y; state->result.width = state->result.height = 1; state->running = false; } else { - seat->anchor_x = seat->x; - seat->anchor_y = seat->y; + current_selection->anchor_x = current_selection->x; + current_selection->anchor_y = current_selection->y; } } static void handle_selection_end(struct slurp_seat *seat) { + struct slurp_selection *current_selection = seat_get_current_selection(seat); struct slurp_state *state = seat->state; if (state->single_point) { return; } - if (seat->has_selection) { - state->result = seat->selection; + if (current_selection->has_selection) { + state->result = current_selection->selection; } state->running = false; } @@ -177,11 +212,15 @@ static void pointer_handle_button(void *data, struct wl_pointer *wl_pointer, uint32_t serial, uint32_t time, uint32_t button, uint32_t button_state) { struct slurp_seat *seat = data; + if (seat->touch_selection.has_selection) { + return; + } seat->button_state = button_state; switch (button_state) { case WL_POINTER_BUTTON_STATE_PRESSED: + seat->pointer_selection.has_selection = true; handle_selection_start(seat); break; case WL_POINTER_BUTTON_STATE_RELEASED: @@ -234,13 +273,15 @@ static void keyboard_handle_key(void *data, struct wl_keyboard *wl_keyboard, case WL_KEYBOARD_KEY_STATE_PRESSED: switch (keysym) { case XKB_KEY_Escape: - seat->has_selection = false; + seat->pointer_selection.has_selection = false; + seat->touch_selection.has_selection = false; state->edit_anchor = false; state->running = false; break; case XKB_KEY_space: - if (!seat->has_selection) { + if (!seat->pointer_selection.has_selection && + !seat->touch_selection.has_selection) { break; } state->edit_anchor = true; @@ -279,10 +320,14 @@ static void touch_handle_down(void *data, struct wl_touch *touch, struct wl_surface *surface, int32_t id, wl_fixed_t x, wl_fixed_t y) { struct slurp_seat *seat = data; + if (seat->pointer_selection.has_selection) { + return; + } if (seat->touch_id == TOUCH_ID_EMPTY) { seat->touch_id = id; - seat->current_output = + seat->touch_selection.current_output = output_from_surface(seat->state, surface); + seat->touch_selection.has_selection = true; move_seat(seat, x, y); handle_selection_start(seat); } @@ -290,7 +335,7 @@ static void touch_handle_down(void *data, struct wl_touch *touch, static void touch_clear_state(struct slurp_seat *seat) { seat->touch_id = TOUCH_ID_EMPTY; - seat->current_output = NULL; + seat->touch_selection.current_output = NULL; } static void touch_handle_up(void *data, struct wl_touch *touch, uint32_t serial, diff --git a/render.c b/render.c index b58124b..6633339 100644 --- a/render.c +++ b/render.c @@ -6,15 +6,16 @@ #include "render.h" #include "slurp.h" -static void set_source_u32(cairo_t *cairo, uint32_t color) { - cairo_set_source_rgba(cairo, - (color >> (3*8) & 0xFF) / 255.0, - (color >> (2*8) & 0xFF) / 255.0, - (color >> (1*8) & 0xFF) / 255.0, - (color >> (0*8) & 0xFF) / 255.0); +static void set_source_u32(cairo_t *cairo, uint32_t color) +{ + cairo_set_source_rgba(cairo, (color >> (3 * 8) & 0xFF) / 255.0, + (color >> (2 * 8) & 0xFF) / 255.0, + (color >> (1 * 8) & 0xFF) / 255.0, + (color >> (0 * 8) & 0xFF) / 255.0); } -void render(struct slurp_output *output) { +void render(struct slurp_output *output) +{ struct slurp_state *state = output->state; struct pool_buffer *buffer = output->current_buffer; cairo_t *cairo = buffer->cairo; @@ -26,39 +27,49 @@ void render(struct slurp_output *output) { cairo_paint(cairo); struct slurp_seat *seat; - wl_list_for_each(seat, &state->seats, link) { - if (!seat->wl_pointer) continue; - if (!seat->has_selection) { + wl_list_for_each(seat, &state->seats, link) + { + struct slurp_selection *current_selection = + seat_get_current_selection(seat); + if (current_selection == NULL) + continue; + if (!seat->wl_pointer) + continue; + if (!current_selection->has_selection) { continue; } - if(!box_intersect(&output->logical_geometry, &seat->selection)) { + if (!box_intersect(&output->logical_geometry, + ¤t_selection->selection)) { continue; } - struct slurp_box b = seat->selection; + struct slurp_box b = current_selection->selection; b.x -= output->logical_geometry.x; b.y -= output->logical_geometry.y; // Draw border set_source_u32(cairo, state->colors.selection); cairo_rectangle(cairo, b.x * scale, b.y * scale, - b.width * scale, b.height * scale); + b.width * scale, b.height * scale); cairo_fill(cairo); set_source_u32(cairo, state->colors.border); cairo_set_line_width(cairo, state->border_weight * scale); cairo_rectangle(cairo, b.x * scale, b.y * scale, - b.width * scale, b.height * scale); + b.width * scale, b.height * scale); cairo_stroke(cairo); if (state->display_dimensions) { - cairo_select_font_face(cairo, "Sans", CAIRO_FONT_SLANT_NORMAL, - CAIRO_FONT_WEIGHT_NORMAL); + cairo_select_font_face(cairo, "Sans", + CAIRO_FONT_SLANT_NORMAL, + CAIRO_FONT_WEIGHT_NORMAL); cairo_set_font_size(cairo, 14 * scale); // buffer of 12 can hold selections up to 99999x99999 char dimensions[12]; - snprintf(dimensions, sizeof(dimensions), "%ix%i", b.width, b.height); - cairo_move_to(cairo, (b.x + b.width + 10) * scale, (b.y + b.height + 20) * scale); + snprintf(dimensions, sizeof(dimensions), "%ix%i", + b.width, b.height); + cairo_move_to(cairo, (b.x + b.width + 10) * scale, + (b.y + b.height + 20) * scale); cairo_show_text(cairo, dimensions); } }