Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix empty selection when user doesn't move their cursor #59

Merged
merged 2 commits into from
Aug 3, 2020
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
102 changes: 54 additions & 48 deletions main.c
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,25 @@ bool box_intersect(const struct slurp_box *a, const struct slurp_box *b) {
a->height + a->y > b->y;
}

static bool in_box(const struct slurp_box *box, int32_t x, int32_t y) {
return box->x <= x
&& box->x + box->width >= x
&& box->y <= y
&& box->y + box->height >= y;
}

static int32_t box_size(const struct slurp_box *box) {
return box->width * box->height;
}

static int min(int a, int b) {
return (a < b) ? a : b;
}

static int max(int a, int b) {
return (a > b) ? a : b;
}

static struct slurp_output *output_from_surface(struct slurp_state *state,
struct wl_surface *surface);

Expand All @@ -45,6 +64,38 @@ static void move_seat(struct slurp_seat *seat, wl_fixed_t surface_x,
current_selection->y = y;
}

static void seat_update_selection(struct slurp_seat *seat) {
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->pointer_selection.x,
seat->pointer_selection.y)) {
if (seat->pointer_selection.has_selection &&
box_size(
&seat->pointer_selection.selection) <
box_size(box)) {
continue;
}
seat->pointer_selection.selection = *box;
seat->pointer_selection.has_selection = true;
}
}
}

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->pointer_selection.selection) ||
box_intersect(&output->logical_geometry,
&seat->touch_selection.selection)) {
set_output_dirty(output);
}
}
}

static void pointer_handle_enter(void *data, struct wl_pointer *wl_pointer,
uint32_t serial, struct wl_surface *surface,
wl_fixed_t surface_x, wl_fixed_t surface_y) {
Expand All @@ -57,6 +108,8 @@ static void pointer_handle_enter(void *data, struct wl_pointer *wl_pointer,
seat->pointer_selection.current_output = output;

move_seat(seat, surface_x, surface_y, &seat->pointer_selection);
seat_update_selection(seat);
seat_set_outputs_dirty(seat);

wl_surface_set_buffer_scale(seat->cursor_surface, output->scale);
wl_surface_attach(seat->cursor_surface,
Expand All @@ -75,37 +128,6 @@ static void pointer_handle_leave(void *data, struct wl_pointer *wl_pointer,
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->pointer_selection.selection) ||
box_intersect(&output->logical_geometry,
&seat->touch_selection.selection)) {
set_output_dirty(output);
}
}
}

static bool in_box(const struct slurp_box *box, int32_t x, int32_t y) {
return box->x <= x
&& box->x + box->width >= x
&& box->y <= y
&& box->y + box->height >= y;
}

static int32_t box_size(const struct slurp_box *box) {
return box->width * box->height;
}

static int min(int a, int b) {
return (a < b) ? a : b;
}

static int max(int a, int b) {
return (a > b) ? a : b;
}

static void handle_active_selection_motion(struct slurp_seat *seat, struct slurp_selection *current_selection) {
int32_t anchor_x = max(0, current_selection->anchor_x);
int32_t anchor_y = max(0, current_selection->anchor_y);
Expand All @@ -130,23 +152,7 @@ static void pointer_handle_motion(void *data, struct wl_pointer *wl_pointer,

switch (seat->button_state) {
case WL_POINTER_BUTTON_STATE_RELEASED:
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->pointer_selection.x,
seat->pointer_selection.y)) {
if (seat->pointer_selection.has_selection &&
box_size(
&seat->pointer_selection.selection) <
box_size(box)) {
continue;
}
seat->pointer_selection.selection = *box;
seat->pointer_selection.has_selection = true;
}
}
seat_update_selection(seat);
break;
case WL_POINTER_BUTTON_STATE_PRESSED:;
handle_active_selection_motion(seat, &seat->pointer_selection);
Expand Down