Skip to content

Commit

Permalink
feat(screencopy): introduce screencopy features
Browse files Browse the repository at this point in the history
  • Loading branch information
jtheoof committed Dec 2, 2019
1 parent d1e9483 commit 53c9770
Show file tree
Hide file tree
Showing 12 changed files with 195 additions and 26 deletions.
6 changes: 5 additions & 1 deletion build/build.ninja
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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
Expand Down
6 changes: 6 additions & 0 deletions build/compile_commands.json
Original file line number Diff line number Diff line change
Expand Up @@ -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",
Expand Down
4 changes: 4 additions & 0 deletions include/box.h
Original file line number Diff line number Diff line change
@@ -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 changes: 23 additions & 0 deletions include/screencopy.h
Original file line number Diff line number Diff line change
@@ -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);
12 changes: 8 additions & 4 deletions include/swappy.h
Original file line number Diff line number Diff line change
Expand Up @@ -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

Expand Down Expand Up @@ -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;
Expand All @@ -82,6 +84,8 @@ struct swappy_state {
char **argv;
};

struct swappy_buffer;

struct swappy_output {
struct swappy_state *state;
struct wl_output *wl_output;
Expand All @@ -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
};
1 change: 0 additions & 1 deletion include/wayland.h
Original file line number Diff line number Diff line change
Expand Up @@ -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);
1 change: 1 addition & 0 deletions meson.build
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ executable(
'src/box.c',
'src/config.c',
'src/draw.c',
'src/screencopy.c',
'src/wayland.c',
'src/application.c',
]),
Expand Down
8 changes: 7 additions & 1 deletion src/application.c
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@

#include "draw.h"
#include "notification.h"
#include "screencopy.h"
#include "swappy.h"
#include "wayland.h"

Expand Down Expand Up @@ -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;
Expand Down
23 changes: 23 additions & 0 deletions src/box.c
Original file line number Diff line number Diff line change
Expand Up @@ -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);
}
8 changes: 4 additions & 4 deletions src/main.c
Original file line number Diff line number Diff line change
Expand Up @@ -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);
}

Expand Down
112 changes: 112 additions & 0 deletions src/screencopy.c
Original file line number Diff line number Diff line change
@@ -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;
}
17 changes: 2 additions & 15 deletions src/wayland.c
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Expand Down Expand Up @@ -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) {
Expand Down Expand Up @@ -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;
}

Expand Down

0 comments on commit 53c9770

Please sign in to comment.