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

Force select #63

Merged
merged 4 commits into from
Oct 12, 2020
Merged
Show file tree
Hide file tree
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
4 changes: 3 additions & 1 deletion include/slurp.h
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,8 @@
struct slurp_box {
int32_t x, y;
int32_t width, height;
struct wl_list link;
char *label;
struct wl_list link;
};

struct slurp_selection {
Expand Down Expand Up @@ -45,11 +45,13 @@ struct slurp_state {
uint32_t background;
uint32_t border;
uint32_t selection;
uint32_t choice;
} colors;

uint32_t border_weight;
bool display_dimensions;
bool single_point;
bool restrict_selection;
struct wl_list boxes; // slurp_box::link

struct slurp_box result;
Expand Down
38 changes: 31 additions & 7 deletions main.c
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,10 @@
#include "slurp.h"
#include "render.h"

#define BG_COLOR 0xFFFFFF40
#define BORDER_COLOR 0x000000FF
#define SELECTION_COLOR 0x00000000

static void noop() {
// This space intentionally left blank
}
Expand Down Expand Up @@ -167,14 +171,19 @@ static void pointer_handle_motion(void *data, struct wl_pointer *wl_pointer,
static void handle_selection_start(struct slurp_seat *seat,
struct slurp_selection *current_selection) {
struct slurp_state *state = seat->state;
current_selection->has_selection = true;

if (state->single_point) {
state->result.x = current_selection->x;
state->result.y = current_selection->y;
state->result.width = state->result.height = 1;
state->running = false;
} else if (state->restrict_selection) {
if (current_selection->has_selection) {
state->result = current_selection->selection;
state->running = false;
}
} else {
current_selection->has_selection = true;
current_selection->anchor_x = current_selection->x;
current_selection->anchor_y = current_selection->y;
}
Expand All @@ -183,7 +192,7 @@ static void handle_selection_start(struct slurp_seat *seat,
static void handle_selection_end(struct slurp_seat *seat,
struct slurp_selection *current_selection) {
struct slurp_state *state = seat->state;
if (state->single_point) {
if (state->single_point || state->restrict_selection) {
return;
}
if (current_selection->has_selection) {
Expand Down Expand Up @@ -637,10 +646,12 @@ static const char usage[] =
" -b #rrggbbaa Set background color.\n"
" -c #rrggbbaa Set border color.\n"
" -s #rrggbbaa Set selection color.\n"
" -B #rrggbbaa Set option box color.\n"
" -w n Set border weight.\n"
" -f s Set output format.\n"
" -o Select a display output.\n"
" -p Select a single point.\n";
" -p Select a single point.\n"
" -r Restrict selection to predefined boxes.\n";

uint32_t parse_color(const char *color) {
if (color[0] == '#') {
Expand Down Expand Up @@ -736,18 +747,20 @@ int main(int argc, char *argv[]) {

struct slurp_state state = {
.colors = {
.background = 0xFFFFFF40,
.border = 0x000000FF,
.selection = 0x00000000,
.background = BG_COLOR,
.border = BORDER_COLOR,
.selection = SELECTION_COLOR,
.choice = BG_COLOR,
},
.border_weight = 2,
.display_dimensions = false,
.restrict_selection = false,
};

int opt;
char *format = "%x,%y %wx%h\n";
bool output_boxes = false;
while ((opt = getopt(argc, argv, "hdb:c:s:w:pof:")) != -1) {
while ((opt = getopt(argc, argv, "hdb:c:s:B:w:prof:")) != -1) {
switch (opt) {
case 'h':
printf("%s", usage);
Expand All @@ -764,6 +777,9 @@ int main(int argc, char *argv[]) {
case 's':
state.colors.selection = parse_color(optarg);
break;
case 'B':
state.colors.choice = parse_color(optarg);
break;
case 'f':
format = optarg;
break;
Expand All @@ -783,12 +799,20 @@ int main(int argc, char *argv[]) {
case 'o':
output_boxes = true;
break;
case 'r':
state.restrict_selection = true;
break;
default:
printf("%s", usage);
return EXIT_FAILURE;
}
}

if (state.single_point && state.restrict_selection) {
fprintf(stderr, "-p and -r cannot be used together\n");
return EXIT_FAILURE;
}

wl_list_init(&state.boxes);
if (!isatty(STDIN_FILENO) && !state.single_point) {
char *line = NULL;
Expand Down
40 changes: 29 additions & 11 deletions render.c
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,17 @@ static void set_source_u32(cairo_t *cairo, uint32_t color) {
(color >> (0 * 8) & 0xFF) / 255.0);
}

static void draw_rect(cairo_t *cairo, struct slurp_box *box, uint32_t color, int32_t scale) {
set_source_u32(cairo, color);
cairo_rectangle(cairo, box->x * scale, box->y * scale,
box->width * scale, box->height * scale);
}

static void box_layout_to_output(struct slurp_box *box, struct slurp_output *output) {
box->x -= output->logical_geometry.x;
box->y -= output->logical_geometry.y;
}

void render(struct slurp_output *output) {
struct slurp_state *state = output->state;
struct pool_buffer *buffer = output->current_buffer;
Expand All @@ -24,35 +35,42 @@ void render(struct slurp_output *output) {
set_source_u32(cairo, state->colors.background);
cairo_paint(cairo);

// Draw option boxes from input
struct slurp_box *choice_box;
wl_list_for_each(choice_box, &state->boxes, link) {
if (box_intersect(&output->logical_geometry,
choice_box)) {
struct slurp_box b = *choice_box;
box_layout_to_output(&b, output);
draw_rect(cairo, &b, state->colors.choice, scale);
cairo_fill(cairo);
}
}

struct slurp_seat *seat;
wl_list_for_each(seat, &state->seats, link) {
struct slurp_selection *current_selection =
seat->touch_selection.has_selection ?
&seat->touch_selection :
&seat->pointer_selection;

if (!seat->wl_pointer) {
if (!current_selection->has_selection) {
continue;
}

if (!box_intersect(&output->logical_geometry,
&current_selection->selection)) {
continue;
}
struct slurp_box b = current_selection->selection;
b.x -= output->logical_geometry.x;
b.y -= output->logical_geometry.y;
box_layout_to_output(&b, output);

// Draw border
set_source_u32(cairo, state->colors.selection);
cairo_rectangle(cairo, b.x * scale, b.y * scale,
b.width * scale, b.height * scale);
draw_rect(cairo, &b, state->colors.selection, scale);
cairo_fill(cairo);

set_source_u32(cairo, state->colors.border);
// Draw 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);
draw_rect(cairo, &b, state->colors.border, scale);
cairo_stroke(cairo);

if (state->display_dimensions) {
Expand Down
13 changes: 11 additions & 2 deletions slurp.1.scd
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,8 @@ slurp is a command-line utility to select a region from Wayland compositors
which support the layer-shell protocol. It lets the user hold the pointer to
select, or click to cancel the selection.

If the standard input is not a TTY, slurp will read a list of predefined
rectangles for quick selection. Each line must be in the form
If the standard input is not a TTY or the -r option is used, slurp will read a
list of predefined rectangles for quick selection. Each line must be in the form
"<x>,<y> <width>x<height> [label]". The label is optional and can be any string
that doesn't contain newlines. It can be accessed using the "%l" sequence in a
format string.
Expand All @@ -40,6 +40,10 @@ held, the selection is moved instead of being resized.
*-s* _color_
Set selection color. See *COLORS* for more detail.

*-B* _color_
Set color for highlighting predefined rectangles from standard input when not
selected.

*-w* _weight_
Set border weight.

Expand All @@ -54,6 +58,11 @@ held, the selection is moved instead of being resized.
Add predefined rectangles for all outputs, as if provided on standard input.
The label will be the name of the output.

*-r*
Require the user to select one of the predefined rectangles. These can come
from standard input, if *-o* is used, the rectangles of all display outputs.
This option conflicts with *-p*.

# COLORS

Colors may be specified in #RRGGBB or #RRGGBBAA format. The # is optional.
Expand Down