feat(screencopy): introduce screencopy features

This commit is contained in:
Jeremy Attali 2019-12-02 00:05:32 -05:00
parent d1e9483ae6
commit 53c9770808
12 changed files with 195 additions and 26 deletions

View File

@ -127,6 +127,10 @@ build swappy@exe/src_draw.c.o: c_COMPILER ../src/draw.c || swappy@exe/xdg-shell-
DEPFILE = swappy@exe/src_draw.c.o.d
ARGS = -Iswappy@exe -I. -I.. -I../include -I/usr/include/cairo -I/usr/include/glib-2.0 -I/usr/lib/glib-2.0/include -I/usr/lib/libffi-3.2.1/include -I/usr/include/pixman-1 -I/usr/include/freetype2 -I/usr/include/libpng16 -I/usr/include/harfbuzz -I/usr/include/gtk-3.0 -I/usr/include/pango-1.0 -I/usr/include/fribidi -I/usr/include/gdk-pixbuf-2.0 -I/usr/include/libmount -I/usr/include/blkid -I/usr/include/gio-unix-2.0 -I/usr/include/atk-1.0 -I/usr/include/at-spi2-atk/2.0 -I/usr/include/at-spi-2.0 -I/usr/include/dbus-1.0 -I/usr/lib/dbus-1.0/include -I/usr/include/gtk-layer-shell -Xclang -fcolor-diagnostics -pipe -D_FILE_OFFSET_BITS=64 -Wall -Winvalid-pch -Wextra -Werror -std=c11 -g -Wno-unused-parameter -pthread
build swappy@exe/src_screencopy.c.o: c_COMPILER ../src/screencopy.c || swappy@exe/xdg-shell-client-protocol.h swappy@exe/xdg-output-unstable-v1-client-protocol.h swappy@exe/wlr-layer-shell-unstable-v1-client-protocol.h swappy@exe/wlr-screencopy-unstable-v1-client-protocol.h protocol/2ea88c7@@client_protos@sta/xdg-shell-client-protocol.h protocol/2ea88c7@@client_protos@sta/xdg-output-unstable-v1-client-protocol.h protocol/2ea88c7@@client_protos@sta/wlr-layer-shell-unstable-v1-client-protocol.h protocol/2ea88c7@@client_protos@sta/wlr-screencopy-unstable-v1-client-protocol.h
DEPFILE = swappy@exe/src_screencopy.c.o.d
ARGS = -Iswappy@exe -I. -I.. -I../include -I/usr/include/cairo -I/usr/include/glib-2.0 -I/usr/lib/glib-2.0/include -I/usr/lib/libffi-3.2.1/include -I/usr/include/pixman-1 -I/usr/include/freetype2 -I/usr/include/libpng16 -I/usr/include/harfbuzz -I/usr/include/gtk-3.0 -I/usr/include/pango-1.0 -I/usr/include/fribidi -I/usr/include/gdk-pixbuf-2.0 -I/usr/include/libmount -I/usr/include/blkid -I/usr/include/gio-unix-2.0 -I/usr/include/atk-1.0 -I/usr/include/at-spi2-atk/2.0 -I/usr/include/at-spi-2.0 -I/usr/include/dbus-1.0 -I/usr/lib/dbus-1.0/include -I/usr/include/gtk-layer-shell -Xclang -fcolor-diagnostics -pipe -D_FILE_OFFSET_BITS=64 -Wall -Winvalid-pch -Wextra -Werror -std=c11 -g -Wno-unused-parameter -pthread
build swappy@exe/src_wayland.c.o: c_COMPILER ../src/wayland.c || swappy@exe/xdg-shell-client-protocol.h swappy@exe/xdg-output-unstable-v1-client-protocol.h swappy@exe/wlr-layer-shell-unstable-v1-client-protocol.h swappy@exe/wlr-screencopy-unstable-v1-client-protocol.h protocol/2ea88c7@@client_protos@sta/xdg-shell-client-protocol.h protocol/2ea88c7@@client_protos@sta/xdg-output-unstable-v1-client-protocol.h protocol/2ea88c7@@client_protos@sta/wlr-layer-shell-unstable-v1-client-protocol.h protocol/2ea88c7@@client_protos@sta/wlr-screencopy-unstable-v1-client-protocol.h
DEPFILE = swappy@exe/src_wayland.c.o.d
ARGS = -Iswappy@exe -I. -I.. -I../include -I/usr/include/cairo -I/usr/include/glib-2.0 -I/usr/lib/glib-2.0/include -I/usr/lib/libffi-3.2.1/include -I/usr/include/pixman-1 -I/usr/include/freetype2 -I/usr/include/libpng16 -I/usr/include/harfbuzz -I/usr/include/gtk-3.0 -I/usr/include/pango-1.0 -I/usr/include/fribidi -I/usr/include/gdk-pixbuf-2.0 -I/usr/include/libmount -I/usr/include/blkid -I/usr/include/gio-unix-2.0 -I/usr/include/atk-1.0 -I/usr/include/at-spi2-atk/2.0 -I/usr/include/at-spi-2.0 -I/usr/include/dbus-1.0 -I/usr/lib/dbus-1.0/include -I/usr/include/gtk-layer-shell -Xclang -fcolor-diagnostics -pipe -D_FILE_OFFSET_BITS=64 -Wall -Winvalid-pch -Wextra -Werror -std=c11 -g -Wno-unused-parameter -pthread
@ -135,7 +139,7 @@ build swappy@exe/src_application.c.o: c_COMPILER ../src/application.c || swappy@
DEPFILE = swappy@exe/src_application.c.o.d
ARGS = -Iswappy@exe -I. -I.. -I../include -I/usr/include/cairo -I/usr/include/glib-2.0 -I/usr/lib/glib-2.0/include -I/usr/lib/libffi-3.2.1/include -I/usr/include/pixman-1 -I/usr/include/freetype2 -I/usr/include/libpng16 -I/usr/include/harfbuzz -I/usr/include/gtk-3.0 -I/usr/include/pango-1.0 -I/usr/include/fribidi -I/usr/include/gdk-pixbuf-2.0 -I/usr/include/libmount -I/usr/include/blkid -I/usr/include/gio-unix-2.0 -I/usr/include/atk-1.0 -I/usr/include/at-spi2-atk/2.0 -I/usr/include/at-spi-2.0 -I/usr/include/dbus-1.0 -I/usr/lib/dbus-1.0/include -I/usr/include/gtk-layer-shell -Xclang -fcolor-diagnostics -pipe -D_FILE_OFFSET_BITS=64 -Wall -Winvalid-pch -Wextra -Werror -std=c11 -g -Wno-unused-parameter -pthread
build swappy: c_LINKER swappy@exe/src_main.c.o swappy@exe/src_notification.c.o swappy@exe/src_box.c.o swappy@exe/src_config.c.o swappy@exe/src_draw.c.o swappy@exe/src_wayland.c.o swappy@exe/src_application.c.o | /usr/lib/librt.a /usr/lib/librt-2.30.so /usr/lib/libcairo.so /usr/lib/libgtk-3.so /usr/lib/libgdk-3.so /usr/lib/libz.so /usr/lib/libpangocairo-1.0.so /usr/lib/libpango-1.0.so /usr/lib/libharfbuzz.so /usr/lib/libatk-1.0.so /usr/lib/libcairo-gobject.so /usr/lib/libgdk_pixbuf-2.0.so /usr/lib/libgio-2.0.so /usr/lib/libgobject-2.0.so /usr/lib/libglib-2.0.so /usr/lib/libgtk-layer-shell.so /usr/lib/libnotify.so /usr/lib/libwayland-client.so /usr/lib/libwayland-cursor.so protocol/libclient_protos.a
build swappy: c_LINKER swappy@exe/src_main.c.o swappy@exe/src_notification.c.o swappy@exe/src_box.c.o swappy@exe/src_config.c.o swappy@exe/src_draw.c.o swappy@exe/src_screencopy.c.o swappy@exe/src_wayland.c.o swappy@exe/src_application.c.o | /usr/lib/librt.a /usr/lib/librt-2.30.so /usr/lib/libcairo.so /usr/lib/libgtk-3.so /usr/lib/libgdk-3.so /usr/lib/libz.so /usr/lib/libpangocairo-1.0.so /usr/lib/libpango-1.0.so /usr/lib/libharfbuzz.so /usr/lib/libatk-1.0.so /usr/lib/libcairo-gobject.so /usr/lib/libgdk_pixbuf-2.0.so /usr/lib/libgio-2.0.so /usr/lib/libgobject-2.0.so /usr/lib/libglib-2.0.so /usr/lib/libgtk-layer-shell.so /usr/lib/libnotify.so /usr/lib/libwayland-client.so /usr/lib/libwayland-cursor.so protocol/libclient_protos.a
LINK_ARGS = -Wl,--as-needed -Wl,--no-undefined -Wl,--start-group protocol/libclient_protos.a /usr/lib/libcairo.so /usr/lib/libgtk-3.so /usr/lib/libgdk-3.so /usr/lib/libz.so /usr/lib/libpangocairo-1.0.so /usr/lib/libpango-1.0.so /usr/lib/libharfbuzz.so /usr/lib/libatk-1.0.so /usr/lib/libcairo-gobject.so /usr/lib/libgdk_pixbuf-2.0.so /usr/lib/libgio-2.0.so /usr/lib/libgobject-2.0.so /usr/lib/libglib-2.0.so /usr/lib/libgtk-layer-shell.so /usr/lib/libnotify.so -lrt /usr/lib/libwayland-client.so /usr/lib/libwayland-cursor.so -Wl,--end-group '-Wl,-rpath,$$ORIGIN/protocol' -Wl,-rpath-link,/home/jattali/dev/jtheoof/swappy/build/protocol
build swappy.1: CUSTOM_COMMAND ../swappy.1.scd | /usr/bin/sh

View File

@ -53,6 +53,12 @@
"file": "../src/draw.c",
"output": "swappy@exe/src_draw.c.o"
},
{
"directory": "/home/jattali/dev/jtheoof/swappy/build",
"command": "clang -Iswappy@exe -I. -I.. -I../include -I/usr/include/cairo -I/usr/include/glib-2.0 -I/usr/lib/glib-2.0/include -I/usr/lib/libffi-3.2.1/include -I/usr/include/pixman-1 -I/usr/include/freetype2 -I/usr/include/libpng16 -I/usr/include/harfbuzz -I/usr/include/gtk-3.0 -I/usr/include/pango-1.0 -I/usr/include/fribidi -I/usr/include/gdk-pixbuf-2.0 -I/usr/include/libmount -I/usr/include/blkid -I/usr/include/gio-unix-2.0 -I/usr/include/atk-1.0 -I/usr/include/at-spi2-atk/2.0 -I/usr/include/at-spi-2.0 -I/usr/include/dbus-1.0 -I/usr/lib/dbus-1.0/include -I/usr/include/gtk-layer-shell -Xclang -fcolor-diagnostics -pipe -D_FILE_OFFSET_BITS=64 -Wall -Winvalid-pch -Wextra -Werror -std=c11 -g -Wno-unused-parameter -pthread -MD -MQ 'swappy@exe/src_screencopy.c.o' -MF 'swappy@exe/src_screencopy.c.o.d' -o 'swappy@exe/src_screencopy.c.o' -c ../src/screencopy.c",
"file": "../src/screencopy.c",
"output": "swappy@exe/src_screencopy.c.o"
},
{
"directory": "/home/jattali/dev/jtheoof/swappy/build",
"command": "clang -Iswappy@exe -I. -I.. -I../include -I/usr/include/cairo -I/usr/include/glib-2.0 -I/usr/lib/glib-2.0/include -I/usr/lib/libffi-3.2.1/include -I/usr/include/pixman-1 -I/usr/include/freetype2 -I/usr/include/libpng16 -I/usr/include/harfbuzz -I/usr/include/gtk-3.0 -I/usr/include/pango-1.0 -I/usr/include/fribidi -I/usr/include/gdk-pixbuf-2.0 -I/usr/include/libmount -I/usr/include/blkid -I/usr/include/gio-unix-2.0 -I/usr/include/atk-1.0 -I/usr/include/at-spi2-atk/2.0 -I/usr/include/at-spi-2.0 -I/usr/include/dbus-1.0 -I/usr/lib/dbus-1.0/include -I/usr/include/gtk-layer-shell -Xclang -fcolor-diagnostics -pipe -D_FILE_OFFSET_BITS=64 -Wall -Winvalid-pch -Wextra -Werror -std=c11 -g -Wno-unused-parameter -pthread -MD -MQ 'swappy@exe/src_wayland.c.o' -MF 'swappy@exe/src_wayland.c.o.d' -o 'swappy@exe/src_wayland.c.o' -c ../src/wayland.c",

View File

@ -1,3 +1,7 @@
#pragma once
#include "swappy.h"
bool box_parse(struct swappy_box *box, const char *str);
bool is_empty_box(struct swappy_box *box);
bool intersect_box(struct swappy_box *a, struct swappy_box *b);

23
include/screencopy.h Normal file
View File

@ -0,0 +1,23 @@
#pragma once
#include <stdio.h>
#include <wayland-client.h>
#include "swappy.h"
#include "wlr-screencopy-unstable-v1-client-protocol.h"
void screencopy_frame_handle_buffer(void *data,
struct zwlr_screencopy_frame_v1 *frame,
uint32_t format, uint32_t width,
uint32_t height, uint32_t stride);
void screencopy_frame_handle_flags(void *data,
struct zwlr_screencopy_frame_v1 *frame,
uint32_t flags);
void screencopy_frame_handle_ready(void *data,
struct zwlr_screencopy_frame_v1 *frame,
uint32_t tv_sec_hi, uint32_t tv_sec_lo,
uint32_t tv_nsec);
void screencopy_frame_handle_failed(void *data,
struct zwlr_screencopy_frame_v1 *frame);
bool screencopy_init(struct swappy_state *state);
bool screencopy_parse_geometry(struct swappy_state *state);

View File

@ -7,9 +7,9 @@
#include <stdlib.h>
#include <wayland-client.h>
#include "xdg-output-unstable-v1-client-protocol.h"
#include "wlr-layer-shell-unstable-v1-client-protocol.h"
#include "wlr-screencopy-unstable-v1-client-protocol.h"
#include "xdg-output-unstable-v1-client-protocol.h"
#define MAX_PATH 4096
@ -61,6 +61,8 @@ struct swappy_state {
struct wl_surface *surface;
struct zwlr_layer_surface_v1 *layer_surface;
size_t n_done;
bool should_exit;
char *storage_path;
@ -82,6 +84,8 @@ struct swappy_state {
char **argv;
};
struct swappy_buffer;
struct swappy_output {
struct swappy_state *state;
struct wl_output *wl_output;
@ -93,10 +97,10 @@ struct swappy_output {
int32_t scale;
struct swappy_box logical_geometry;
double logical_scale; // guessed from the logical size
double logical_scale; // guessed from the logical size
char *name;
// struct swappy_buffer *buffer;
struct swappy_buffer *buffer;
struct zwlr_screencopy_frame_v1 *screencopy_frame;
uint32_t screencopy_frame_flags; // enum zwlr_screencopy_frame_v1_flags
uint32_t screencopy_frame_flags; // enum zwlr_screencopy_frame_v1_flags
};

View File

@ -4,4 +4,3 @@
bool wayland_init(struct swappy_state *state);
void wayland_finish(struct swappy_state *state);
bool wayland_screencopy_geometry(struct swappy_state *state);

View File

@ -37,6 +37,7 @@ executable(
'src/box.c',
'src/config.c',
'src/draw.c',
'src/screencopy.c',
'src/wayland.c',
'src/application.c',
]),

View File

@ -6,6 +6,7 @@
#include "draw.h"
#include "notification.h"
#include "screencopy.h"
#include "swappy.h"
#include "wayland.h"
@ -272,10 +273,15 @@ static gint command_line_handler(GtkApplication *app,
g_debug("geometry is: %s", state->geometry_str);
if (!wayland_screencopy_geometry(state)) {
if (!screencopy_parse_geometry(state)) {
return EXIT_FAILURE;
}
if (!screencopy_init(state)) {
g_warning("unable to initialize zwlr_screencopy_v1");
return false;
}
init_layer_shell(app, state);
return EXIT_SUCCESS;

View File

@ -28,3 +28,26 @@ bool box_parse(struct swappy_box *box, const char *str) {
return true;
}
bool is_empty_box(struct swappy_box *box) {
return box->width <= 0 || box->height <= 0;
}
bool intersect_box(struct swappy_box *a, struct swappy_box *b) {
if (is_empty_box(a) || is_empty_box(b)) {
return false;
}
int x1 = fmax(a->x, b->x);
int y1 = fmax(a->y, b->y);
int x2 = fmin(a->x + a->width, b->x + b->width);
int y2 = fmin(a->y + a->height, b->y + b->height);
struct swappy_box box = {
.x = x1,
.y = y1,
.width = x2 - x1,
.height = y2 - y1,
};
return !is_empty_box(&box);
}

View File

@ -31,13 +31,13 @@ int main(int argc, char *argv[]) {
exit(1);
}
if (!wayland_init(&state)) {
g_critical("failed to initialize wayland");
if (!application_init(&state)) {
g_critical("failed to initialize gtk application");
exit(1);
}
if (!application_init(&state)) {
g_critical("failed to initialize gtk application");
if (!wayland_init(&state)) {
g_critical("failed to initialize wayland");
exit(1);
}

112
src/screencopy.c Normal file
View File

@ -0,0 +1,112 @@
#include "screencopy.h"
#include <stdio.h>
#include <string.h>
#include <wayland-client.h>
#include "box.h"
#include "swappy.h"
#include "wlr-screencopy-unstable-v1-client-protocol.h"
static struct swappy_buffer *create_buffer(struct wl_shm *shm,
enum wl_shm_format format,
int32_t width, int32_t height,
int32_t stride) {
return NULL;
}
void screencopy_frame_handle_buffer(void *data,
struct zwlr_screencopy_frame_v1 *frame,
uint32_t format, uint32_t width,
uint32_t height, uint32_t stride) {
g_debug("screencopy: frame handler buffer: %dx%d", width, height);
struct swappy_output *output = data;
output->buffer =
create_buffer(output->state->shm, format, width, height, stride);
if (output->buffer == NULL) {
g_warning("failed to create buffer");
exit(EXIT_FAILURE);
}
// zwlr_screencopy_frame_v1_copy(frame, output->buffer->wl_buffer);
}
void screencopy_frame_handle_flags(void *data,
struct zwlr_screencopy_frame_v1 *frame,
uint32_t flags) {
g_debug("screencopy: frame flags: %d", flags);
struct swappy_output *output = data;
output->screencopy_frame_flags = flags;
}
void screencopy_frame_handle_ready(void *data,
struct zwlr_screencopy_frame_v1 *frame,
uint32_t tv_sec_hi, uint32_t tv_sec_lo,
uint32_t tv_nsec) {
struct swappy_output *output = data;
g_debug("screencopy: frame handler is ready");
++output->state->n_done;
}
void screencopy_frame_handle_failed(void *data,
struct zwlr_screencopy_frame_v1 *frame) {
struct swappy_output *output = data;
g_warning("screencopy: failed to copy output %s", output->name);
exit(EXIT_FAILURE);
}
bool screencopy_init(struct swappy_state *state) {
int32_t with_cursor = 0;
size_t n_pending = 0;
struct swappy_output *output;
const struct zwlr_screencopy_frame_v1_listener screencopy_frame_listener = {
.buffer = screencopy_frame_handle_buffer,
.flags = screencopy_frame_handle_flags,
.ready = screencopy_frame_handle_ready,
.failed = screencopy_frame_handle_failed,
};
wl_list_for_each(output, &state->outputs, link) {
if (state->geometry != NULL &&
!intersect_box(state->geometry, &output->logical_geometry)) {
continue;
}
output->screencopy_frame = zwlr_screencopy_manager_v1_capture_output(
state->zwlr_screencopy_manager, with_cursor, output->wl_output);
zwlr_screencopy_frame_v1_add_listener(output->screencopy_frame,
&screencopy_frame_listener, output);
++n_pending;
}
if (n_pending == 0) {
g_warning("screencopy: region is empty");
return EXIT_FAILURE;
}
bool done = false;
while (!done && wl_display_dispatch(state->display) != -1) {
done = (state->n_done == n_pending);
}
if (!done) {
g_warning("failed to screenshoot all outputs");
return EXIT_FAILURE;
}
return true;
}
bool screencopy_parse_geometry(struct swappy_state *state) {
struct swappy_box *geometry = g_new(struct swappy_box, 1);
char *geometry_str = state->geometry_str;
state->geometry = geometry;
if (!box_parse(geometry, geometry_str)) {
g_critical("%s is not a valid geometry, must follow the pattern \"%s",
geometry_str, GEOMETRY_PATTERN);
return false;
}
return true;
}

View File

@ -4,7 +4,7 @@
#include <string.h>
#include <wayland-client.h>
#include "box.h"
#include "screencopy.h"
#include "swappy.h"
#include "wlr-layer-shell-unstable-v1-client-protocol.h"
#include "wlr-screencopy-unstable-v1-client-protocol.h"
@ -115,19 +115,6 @@ static const struct wl_output_listener output_listener = {
.scale = output_handle_scale,
};
bool wayland_screencopy_geometry(struct swappy_state *state) {
struct swappy_box *geometry = g_new(struct swappy_box, 1);
char *geometry_str = state->geometry_str;
state->geometry = geometry;
if (!box_parse(geometry, geometry_str)) {
g_critical("%s is not a valid geometry, must follow the pattern \"%s",
geometry_str, GEOMETRY_PATTERN);
return false;
}
return true;
}
static void global_registry_handler(void *data, struct wl_registry *registry,
uint32_t name, const char *interface,
uint32_t version) {
@ -163,7 +150,7 @@ static void global_registry_handler(void *data, struct wl_registry *registry,
} else if (strcmp(interface, zwlr_screencopy_manager_v1_interface.name) ==
0) {
state->zwlr_screencopy_manager = wl_registry_bind(
registry, name, &zwlr_screencopy_manager_v1_interface, 1);
registry, name, &zwlr_screencopy_manager_v1_interface, version);
bound = true;
}