From e3b420f8c87f2a1dc55fc69a7f474ffe22124995 Mon Sep 17 00:00:00 2001 From: David Pedersen Date: Mon, 25 Jun 2018 21:34:02 +0200 Subject: [PATCH 1/9] Display dimensions of selection --- include/slurp.h | 1 + main.c | 11 +++++++++-- render.c | 12 ++++++++++++ slurp.1.scd | 3 +++ 4 files changed, 25 insertions(+), 2 deletions(-) diff --git a/include/slurp.h b/include/slurp.h index c046462..e77f036 100644 --- a/include/slurp.h +++ b/include/slurp.h @@ -41,6 +41,7 @@ struct slurp_output { bool configured; bool frame_scheduled; bool dirty; + bool display_dimensions; int32_t width, height; struct pool_buffer buffers[2]; struct pool_buffer *current_buffer; diff --git a/main.c b/main.c index c3bdf90..af54d24 100644 --- a/main.c +++ b/main.c @@ -320,15 +320,20 @@ static const struct wl_registry_listener registry_listener = { static const char usage[] = "Usage: slurp [options...]\n" "\n" - " -h Show help message and quit.\n"; + " -h Show help message and quit.\n" + " -d Display dimensions of selection.\n"; int main(int argc, char *argv[]) { + bool display_dimensions = false; int opt; - while ((opt = getopt(argc, argv, "h")) != -1) { + while ((opt = getopt(argc, argv, "hd")) != -1) { switch (opt) { case 'h': printf("%s", usage); return EXIT_SUCCESS; + case 'd': + display_dimensions = true; + break; default: return EXIT_FAILURE; } @@ -371,6 +376,8 @@ int main(int argc, char *argv[]) { output->surface = wl_compositor_create_surface(state.compositor); // TODO: wl_surface_add_listener(output->surface, &surface_listener, output); + output->display_dimensions = display_dimensions; + output->layer_surface = zwlr_layer_shell_v1_get_layer_surface( state.layer_shell, output->surface, output->wl_output, ZWLR_LAYER_SHELL_V1_LAYER_OVERLAY, "selection"); diff --git a/render.c b/render.c index 5088c51..e34c3fc 100644 --- a/render.c +++ b/render.c @@ -19,6 +19,7 @@ void render(struct slurp_output *output) { struct pool_buffer *buffer = output->current_buffer; cairo_t *cairo = buffer->cairo; int32_t scale = output->scale; + bool display_dimensions = output->display_dimensions; uint32_t border_color = 0x000000FF; int border_size = 2; @@ -40,6 +41,17 @@ void render(struct slurp_output *output) { int x, y, width, height; pointer_get_box(pointer, &x, &y, &width, &height); + if (display_dimensions) { + cairo_select_font_face(cairo, "Sans", CAIRO_FONT_SLANT_NORMAL, + CAIRO_FONT_WEIGHT_NORMAL); + cairo_set_font_size(cairo, 14); + // buffer of 11 can hold selections up to 99999x99999 + char dimensions[11]; + sprintf(dimensions, "%ix%i", width, height); + cairo_move_to(cairo, x + width + 15, y + height + 25); + cairo_show_text(cairo, dimensions); + } + // Draw border set_source_u32(cairo, border_color); cairo_set_line_width(cairo, border_size * scale); diff --git a/slurp.1.scd b/slurp.1.scd index 32572a1..4c5878a 100644 --- a/slurp.1.scd +++ b/slurp.1.scd @@ -19,6 +19,9 @@ select, or click to cancel the selection. *-h* Show help message and quit. +*-d* + Display dimensions of selection. + # AUTHORS Maintained by Simon Ser , who is assisted by other From 6ea82e60eb72456561170bdad6cb5fa68e3cae53 Mon Sep 17 00:00:00 2001 From: David Pedersen Date: Thu, 28 Jun 2018 21:19:07 +0200 Subject: [PATCH 2/9] Keep space in buffer for \0 --- render.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/render.c b/render.c index e34c3fc..538a257 100644 --- a/render.c +++ b/render.c @@ -45,8 +45,8 @@ void render(struct slurp_output *output) { cairo_select_font_face(cairo, "Sans", CAIRO_FONT_SLANT_NORMAL, CAIRO_FONT_WEIGHT_NORMAL); cairo_set_font_size(cairo, 14); - // buffer of 11 can hold selections up to 99999x99999 - char dimensions[11]; + // buffer of 12 can hold selections up to 99999x99999 + char dimensions[12]; sprintf(dimensions, "%ix%i", width, height); cairo_move_to(cairo, x + width + 15, y + height + 25); cairo_show_text(cairo, dimensions); From 790723bb9e55adc7ef0b40f02aaa6b45b65fc965 Mon Sep 17 00:00:00 2001 From: David Pedersen Date: Thu, 28 Jun 2018 21:24:47 +0200 Subject: [PATCH 3/9] Use snprintf instead of sprintf --- render.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/render.c b/render.c index 538a257..d31a3e7 100644 --- a/render.c +++ b/render.c @@ -47,7 +47,7 @@ void render(struct slurp_output *output) { cairo_set_font_size(cairo, 14); // buffer of 12 can hold selections up to 99999x99999 char dimensions[12]; - sprintf(dimensions, "%ix%i", width, height); + snprintf(dimensions, sizeof(dimensions), "%ix%i", width, height); cairo_move_to(cairo, x + width + 15, y + height + 25); cairo_show_text(cairo, dimensions); } From cc1b8d561096373335af4438690524d0b9334638 Mon Sep 17 00:00:00 2001 From: Drew DeVault Date: Sun, 24 Jun 2018 11:16:12 -0400 Subject: [PATCH 4/9] Add appearance customization options --- include/slurp.h | 8 +++++++ main.c | 59 +++++++++++++++++++++++++++++++++++++++++++++---- render.c | 16 +++++++------- slurp.1.scd | 18 ++++++++++++++- 4 files changed, 88 insertions(+), 13 deletions(-) diff --git a/include/slurp.h b/include/slurp.h index e77f036..07ddc5a 100644 --- a/include/slurp.h +++ b/include/slurp.h @@ -24,6 +24,14 @@ struct slurp_state { struct wl_list outputs; // slurp_output::link struct wl_list pointers; // slurp_pointer::link + struct { + uint32_t background; + uint32_t border; + uint32_t selection; + } colors; + + uint32_t border_weight; + struct slurp_box result; }; diff --git a/main.c b/main.c index af54d24..c6bc828 100644 --- a/main.c +++ b/main.c @@ -1,4 +1,5 @@ #define _POSIX_C_SOURCE 2 +#include #include #include #include @@ -320,13 +321,44 @@ static const struct wl_registry_listener registry_listener = { static const char usage[] = "Usage: slurp [options...]\n" "\n" - " -h Show help message and quit.\n" - " -d Display dimensions of selection.\n"; + " -h Show help message and quit.\n" + " -d Display dimensions of selection.\n" + " -b #rrggbb Set background color.\n" + " -c #rrggbb Set border color.\n" + " -s #rrggbb Set selection color.\n" + " -w n Set border weight.\n"; + +uint32_t parse_color(const char *color) { + if (color[0] == '#') { + ++color; + } + + int len = strlen(color); + if (len != 6 && len != 8) { + fprintf(stderr, "Invalid color %s, " + "defaulting to color 0xFFFFFFFF\n", color); + return 0xFFFFFFFF; + } + uint32_t res = (uint32_t)strtoul(color, NULL, 16); + if (strlen(color) == 6) { + res = (res << 8) | 0xFF; + } + return res; +} int main(int argc, char *argv[]) { + struct slurp_state state = { + .colors = { + .background = 0xFFFFFF40, + .border = 0x000000FF, + .selection = 0x00000000, + }, + .border_weight = 2, + }; + bool display_dimensions = false; int opt; - while ((opt = getopt(argc, argv, "hd")) != -1) { + while ((opt = getopt(argc, argv, "hdb:c:s:w:")) != -1) { switch (opt) { case 'h': printf("%s", usage); @@ -334,12 +366,31 @@ int main(int argc, char *argv[]) { case 'd': display_dimensions = true; break; + case 'b': + state.colors.background = parse_color(optarg); + break; + case 'c': + state.colors.border = parse_color(optarg); + break; + case 's': + state.colors.selection = parse_color(optarg); + break; + case 'w': { + errno = 0; + char *endptr; + state.border_weight = strtol(optarg, &endptr, 10); + if (*endptr || errno) { + fprintf(stderr, "Error: expected numeric argument for -w\n"); + exit(EXIT_FAILURE); + } + break; + } default: + printf("%s", usage); return EXIT_FAILURE; } } - struct slurp_state state = {0}; wl_list_init(&state.outputs); wl_list_init(&state.pointers); diff --git a/render.c b/render.c index d31a3e7..3a22a31 100644 --- a/render.c +++ b/render.c @@ -21,15 +21,10 @@ void render(struct slurp_output *output) { int32_t scale = output->scale; bool display_dimensions = output->display_dimensions; - uint32_t border_color = 0x000000FF; - int border_size = 2; - // Clear - cairo_save(cairo); - cairo_set_source_rgba(cairo, 0, 0, 0, 0); cairo_set_operator(cairo, CAIRO_OPERATOR_SOURCE); + set_source_u32(cairo, state->colors.background); cairo_paint(cairo); - cairo_restore(cairo); struct slurp_pointer *pointer; wl_list_for_each(pointer, &state->pointers, link) { @@ -53,8 +48,13 @@ void render(struct slurp_output *output) { } // Draw border - set_source_u32(cairo, border_color); - cairo_set_line_width(cairo, border_size * scale); + set_source_u32(cairo, state->colors.selection); + cairo_rectangle(cairo, x * scale, y * scale, + width * scale, height * scale); + cairo_fill(cairo); + + set_source_u32(cairo, state->colors.border); + cairo_set_line_width(cairo, state->border_weight * scale); cairo_rectangle(cairo, x * scale, y * scale, width * scale, height * scale); cairo_stroke(cairo); diff --git a/slurp.1.scd b/slurp.1.scd index 4c5878a..7df00c4 100644 --- a/slurp.1.scd +++ b/slurp.1.scd @@ -11,7 +11,7 @@ slurp - select a region in a Wayland compositor # SYNOPSIS slurp is a command-line utility to select a region from Wayland compositors -which support the layer-shell protocol. It lets the user hold his pointer to +which support the layer-shell protocol. It lets the user hold the pointer to select, or click to cancel the selection. # OPTIONS @@ -22,6 +22,22 @@ select, or click to cancel the selection. *-d* Display dimensions of selection. +*-b* _color_ + Set background color. See *COLORS* for more detail. + +*-c* _color_ + Set border color. See *COLORS* for more detail. + +*-s* _color_ + Set selection color. See *COLORS* for more detail. + +*-w* _weight_ + Set border weight. + +# COLORS + +Colors may be specified in #RRGGBB or #RRGGBBAA format. The # is optional. + # AUTHORS Maintained by Simon Ser , who is assisted by other From c68412ae06cbe5f8ab425a17e8db6344f9b36d22 Mon Sep 17 00:00:00 2001 From: Drew DeVault Date: Sun, 24 Jun 2018 11:01:38 -0400 Subject: [PATCH 5/9] Use a crosshair cursor via wayland-cursor --- include/slurp.h | 5 +++++ main.c | 26 +++++++++++++++++++++++++- meson.build | 2 ++ 3 files changed, 32 insertions(+), 1 deletion(-) diff --git a/include/slurp.h b/include/slurp.h index 07ddc5a..01396e6 100644 --- a/include/slurp.h +++ b/include/slurp.h @@ -53,6 +53,9 @@ struct slurp_output { int32_t width, height; struct pool_buffer buffers[2]; struct pool_buffer *current_buffer; + + struct wl_cursor_theme *cursor_theme; + struct wl_cursor_image *cursor_image; }; struct slurp_pointer { @@ -64,6 +67,8 @@ struct slurp_pointer { int32_t pressed_x, pressed_y; enum wl_pointer_button_state button_state; struct slurp_output *current_output; + + struct wl_surface *cursor_surface; }; void pointer_get_box(struct slurp_pointer *pointer, int *x, int *y, diff --git a/main.c b/main.c index c6bc828..82d8d0d 100644 --- a/main.c +++ b/main.c @@ -1,9 +1,11 @@ #define _POSIX_C_SOURCE 2 +#include #include #include #include #include #include +#include #ifdef __linux__ #include #elif __FreeBSD__ @@ -37,6 +39,14 @@ static void pointer_handle_enter(void *data, struct wl_pointer *wl_pointer, // TODO: handle multiple overlapping outputs pointer->current_output = output; + + wl_surface_set_buffer_scale(pointer->cursor_surface, output->scale); + wl_surface_attach(pointer->cursor_surface, + wl_cursor_image_get_buffer(output->cursor_image), 0, 0); + wl_pointer_set_cursor(wl_pointer, serial, pointer->cursor_surface, + output->cursor_image->hotspot_x / output->scale, + output->cursor_image->hotspot_y / output->scale); + wl_surface_commit(pointer->cursor_surface); } static void pointer_handle_leave(void *data, struct wl_pointer *wl_pointer, @@ -442,6 +452,20 @@ int main(int argc, char *argv[]) { ZWLR_LAYER_SURFACE_V1_ANCHOR_BOTTOM); zwlr_layer_surface_v1_set_exclusive_zone(output->layer_surface, -1); wl_surface_commit(output->surface); + + output->cursor_theme = + wl_cursor_theme_load(NULL, 24 * output->scale, state.shm); + assert(output->cursor_theme); + struct wl_cursor *cursor = + wl_cursor_theme_get_cursor(output->cursor_theme, "crosshair"); + assert(cursor); + output->cursor_image = cursor->images[0]; + } + + struct slurp_pointer *pointer; + wl_list_for_each(pointer, &state.pointers, link) { + pointer->cursor_surface = + wl_compositor_create_surface(state.compositor); } state.running = true; @@ -449,7 +473,7 @@ int main(int argc, char *argv[]) { // This space intentionally left blank } - struct slurp_pointer *pointer, *pointer_tmp; + struct slurp_pointer *pointer_tmp; wl_list_for_each_safe(pointer, pointer_tmp, &state.pointers, link) { destroy_pointer(pointer); } diff --git a/meson.build b/meson.build index 0a0e4af..d76beb2 100644 --- a/meson.build +++ b/meson.build @@ -17,6 +17,7 @@ slurp_inc = include_directories('include') cairo = dependency('cairo') wayland_client = dependency('wayland-client') +wayland_cursor = dependency('wayland-cursor') wayland_protos = dependency('wayland-protocols', version: '>=1.14') subdir('protocol') @@ -32,6 +33,7 @@ executable( cairo, client_protos, wayland_client, + wayland_cursor, ], include_directories: [slurp_inc], install: true, From 53681aa13dcd3a3d93a132dc740d803b83442111 Mon Sep 17 00:00:00 2001 From: David Pedersen Date: Tue, 3 Jul 2018 19:26:32 +0200 Subject: [PATCH 6/9] Moved dimensions section to end of render --- render.c | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/render.c b/render.c index 3a22a31..6a0df99 100644 --- a/render.c +++ b/render.c @@ -36,17 +36,6 @@ void render(struct slurp_output *output) { int x, y, width, height; pointer_get_box(pointer, &x, &y, &width, &height); - if (display_dimensions) { - cairo_select_font_face(cairo, "Sans", CAIRO_FONT_SLANT_NORMAL, - CAIRO_FONT_WEIGHT_NORMAL); - cairo_set_font_size(cairo, 14); - // buffer of 12 can hold selections up to 99999x99999 - char dimensions[12]; - snprintf(dimensions, sizeof(dimensions), "%ix%i", width, height); - cairo_move_to(cairo, x + width + 15, y + height + 25); - cairo_show_text(cairo, dimensions); - } - // Draw border set_source_u32(cairo, state->colors.selection); cairo_rectangle(cairo, x * scale, y * scale, @@ -58,5 +47,16 @@ void render(struct slurp_output *output) { cairo_rectangle(cairo, x * scale, y * scale, width * scale, height * scale); cairo_stroke(cairo); + + if (display_dimensions) { + cairo_select_font_face(cairo, "Sans", CAIRO_FONT_SLANT_NORMAL, + CAIRO_FONT_WEIGHT_NORMAL); + cairo_set_font_size(cairo, 14); + // buffer of 12 can hold selections up to 99999x99999 + char dimensions[12]; + snprintf(dimensions, sizeof(dimensions), "%ix%i", width, height); + cairo_move_to(cairo, x + width + 15, y + height + 25); + cairo_show_text(cairo, dimensions); + } } } From 66d6f243da935c039f65fd3dee3d5cf553705b99 Mon Sep 17 00:00:00 2001 From: David Pedersen Date: Tue, 3 Jul 2018 19:30:38 +0200 Subject: [PATCH 7/9] Moved dimensions closer to crosshair --- render.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/render.c b/render.c index 6a0df99..ebb7401 100644 --- a/render.c +++ b/render.c @@ -55,7 +55,7 @@ void render(struct slurp_output *output) { // buffer of 12 can hold selections up to 99999x99999 char dimensions[12]; snprintf(dimensions, sizeof(dimensions), "%ix%i", width, height); - cairo_move_to(cairo, x + width + 15, y + height + 25); + cairo_move_to(cairo, x + width + 10, y + height + 20); cairo_show_text(cairo, dimensions); } } From 36b653d3e5813d7824deb87e0bdaacba4f6555b1 Mon Sep 17 00:00:00 2001 From: David Pedersen Date: Tue, 3 Jul 2018 19:41:04 +0200 Subject: [PATCH 8/9] Moved dimensions option to state struct --- include/slurp.h | 2 +- main.c | 6 ++---- render.c | 3 +-- 3 files changed, 4 insertions(+), 7 deletions(-) diff --git a/include/slurp.h b/include/slurp.h index 01396e6..7244516 100644 --- a/include/slurp.h +++ b/include/slurp.h @@ -31,6 +31,7 @@ struct slurp_state { } colors; uint32_t border_weight; + bool display_dimensions; struct slurp_box result; }; @@ -49,7 +50,6 @@ struct slurp_output { bool configured; bool frame_scheduled; bool dirty; - bool display_dimensions; int32_t width, height; struct pool_buffer buffers[2]; struct pool_buffer *current_buffer; diff --git a/main.c b/main.c index 82d8d0d..7e29b8b 100644 --- a/main.c +++ b/main.c @@ -364,9 +364,9 @@ int main(int argc, char *argv[]) { .selection = 0x00000000, }, .border_weight = 2, + .display_dimensions = false, }; - bool display_dimensions = false; int opt; while ((opt = getopt(argc, argv, "hdb:c:s:w:")) != -1) { switch (opt) { @@ -374,7 +374,7 @@ int main(int argc, char *argv[]) { printf("%s", usage); return EXIT_SUCCESS; case 'd': - display_dimensions = true; + state.display_dimensions = true; break; case 'b': state.colors.background = parse_color(optarg); @@ -437,8 +437,6 @@ int main(int argc, char *argv[]) { output->surface = wl_compositor_create_surface(state.compositor); // TODO: wl_surface_add_listener(output->surface, &surface_listener, output); - output->display_dimensions = display_dimensions; - output->layer_surface = zwlr_layer_shell_v1_get_layer_surface( state.layer_shell, output->surface, output->wl_output, ZWLR_LAYER_SHELL_V1_LAYER_OVERLAY, "selection"); diff --git a/render.c b/render.c index ebb7401..0bbbc01 100644 --- a/render.c +++ b/render.c @@ -19,7 +19,6 @@ void render(struct slurp_output *output) { struct pool_buffer *buffer = output->current_buffer; cairo_t *cairo = buffer->cairo; int32_t scale = output->scale; - bool display_dimensions = output->display_dimensions; // Clear cairo_set_operator(cairo, CAIRO_OPERATOR_SOURCE); @@ -48,7 +47,7 @@ void render(struct slurp_output *output) { width * scale, height * scale); cairo_stroke(cairo); - if (display_dimensions) { + if (state->display_dimensions) { cairo_select_font_face(cairo, "Sans", CAIRO_FONT_SLANT_NORMAL, CAIRO_FONT_WEIGHT_NORMAL); cairo_set_font_size(cairo, 14); From 22112a6ae3c90912bdaefda8c848448a500952cf Mon Sep 17 00:00:00 2001 From: David Pedersen Date: Tue, 3 Jul 2018 21:51:03 +0200 Subject: [PATCH 9/9] Added HiDPI support to dimensions --- render.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/render.c b/render.c index 0bbbc01..22e0350 100644 --- a/render.c +++ b/render.c @@ -50,11 +50,11 @@ void render(struct slurp_output *output) { if (state->display_dimensions) { cairo_select_font_face(cairo, "Sans", CAIRO_FONT_SLANT_NORMAL, CAIRO_FONT_WEIGHT_NORMAL); - cairo_set_font_size(cairo, 14); + 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", width, height); - cairo_move_to(cairo, x + width + 10, y + height + 20); + cairo_move_to(cairo, (x + width + 10) * scale, (y + height + 20) * scale); cairo_show_text(cairo, dimensions); } }