From 0167c017a0a62b81199a977121d9c052c25bbc44 Mon Sep 17 00:00:00 2001 From: Kirill Primak Date: Thu, 30 Jan 2025 23:11:07 +0300 Subject: [PATCH] seat: allow toggling whole output selection Closes: https://codeberg.org/vyivel/dulcepan/issues/20 --- src/dulcepan.h | 10 ++++++++- src/main.c | 2 +- src/seat.c | 4 ++-- src/select.c | 56 +++++++++++++++++++++++++++++++++++++++++++------- 4 files changed, 61 insertions(+), 11 deletions(-) diff --git a/src/dulcepan.h b/src/dulcepan.h index 05fb755..63d6e90 100644 --- a/src/dulcepan.h +++ b/src/dulcepan.h @@ -126,6 +126,14 @@ struct dp_selection { int resize_edges; // Resize anchor double resize_x, resize_y; + + // Used for toggling + struct { + // If not NULL, the current output has been selected via the dedicated + // action rather than by persistent state loading or manual resizing + struct dp_output *output; + double x, y, width, height; + } last_partial; }; enum dp_file_format { @@ -232,7 +240,7 @@ void dp_select_stop_interactive(struct dp_selection *selection); void dp_select_notify_pointer_position( struct dp_selection *selection, struct dp_output *output, double x, double y); -void dp_select_whole(struct dp_selection *selection, struct dp_output *output); +void dp_select_toggle_whole(struct dp_selection *selection, struct dp_output *output); void dp_save(struct dp_state *state); diff --git a/src/main.c b/src/main.c index e089ec7..7e55949 100644 --- a/src/main.c +++ b/src/main.c @@ -176,7 +176,7 @@ static void help(const char *prog) { "\n" "Use the left or right mouse button to select a part of the output. A selection\n" "can also be moved and resized with the left mouse button. Clicking the middle\n" - "mouse button selects the entire output.\n", + "mouse button toggles the selection of the entire output.\n", prog); } diff --git a/src/seat.c b/src/seat.c index 63b019a..32b12c6 100644 --- a/src/seat.c +++ b/src/seat.c @@ -201,9 +201,9 @@ static void pointer_handle_button(void *data, struct wl_pointer *wl_pointer, uin update_cursor(seat); break; case BTN_MIDDLE: - dp_select_whole(selection, seat->ptr_output); + dp_select_toggle_whole(selection, seat->ptr_output); - // dp_select_whole() doesn't invalidate the interactive state, so do it manually + // Update the interaction state manually dp_select_notify_pointer_position(selection, seat->ptr_output, seat->ptr_x, seat->ptr_y); update_cursor(seat); diff --git a/src/select.c b/src/select.c index 22255c1..ec3d11b 100644 --- a/src/select.c +++ b/src/select.c @@ -20,6 +20,24 @@ static void set_selected_output(struct dp_selection *selection, struct dp_output } } +static inline bool has_last_partial(struct dp_selection *selection) { + return selection->last_partial.output != NULL; +} + +static inline void reset_last_partial(struct dp_selection *selection) { + selection->last_partial.output = NULL; +} + +static bool has_partial(struct dp_selection *selection) { + struct dp_output *output = selection->output; + if (output == NULL) { + return false; + } + + return selection->x != 0 || selection->y != 0 || selection->width != output->effective_width || + selection->height != output->effective_height; +} + static void update_action( struct dp_selection *selection, struct dp_output *output, double x, double y) { if (output == selection->output) { @@ -161,6 +179,8 @@ void dp_select_start_interactive(struct dp_selection *selection, struct dp_outpu update_action(selection, output, x, y); selection->action_active = true; + reset_last_partial(selection); + if (modify_existing) { switch (selection->action) { case DP_SELECTION_ACTION_NONE: @@ -213,13 +233,35 @@ void dp_select_notify_pointer_position( } } -void dp_select_whole(struct dp_selection *selection, struct dp_output *output) { - set_selected_output(selection, output); +void dp_select_toggle_whole(struct dp_selection *selection, struct dp_output *output) { + if (selection->output == output && has_last_partial(selection)) { + // Toggle the selection back to the last partial one + set_selected_output(selection, selection->last_partial.output); - selection->x = 0; - selection->y = 0; - selection->width = output->effective_width; - selection->height = output->effective_height; + selection->x = selection->last_partial.x; + selection->y = selection->last_partial.y; + selection->width = selection->last_partial.width; + selection->height = selection->last_partial.height; - dp_output_redraw(output); + reset_last_partial(selection); + } else { + // Don't save another whole output selection as partial + if (has_partial(selection) && !has_last_partial(selection)) { + selection->last_partial.output = selection->output; + + selection->last_partial.x = selection->x; + selection->last_partial.y = selection->y; + selection->last_partial.width = selection->width; + selection->last_partial.height = selection->height; + } + + set_selected_output(selection, output); + + selection->x = 0; + selection->y = 0; + selection->width = output->effective_width; + selection->height = output->effective_height; + } + + dp_output_redraw(selection->output); }