Skip to content

Commit

Permalink
feat(application): allow print surface to stdout
Browse files Browse the repository at this point in the history
This allows a user to output the final surface to `stdout` using:

- `-O`
- `--print-stdout`

Also adding another keybinding to exit the application `Ctrl+w` which is
pretty standard.

Closes #2
  • Loading branch information
jtheoof committed Jan 20, 2020
1 parent f7752cb commit 60879b2
Show file tree
Hide file tree
Showing 7 changed files with 108 additions and 9 deletions.
24 changes: 24 additions & 0 deletions .vscode/launch.json
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,30 @@
}
]
},
{
"name": "swappy - file & stdout",
"type": "cppdbg",
"request": "launch",
"program": "${workspaceFolder}/build/swappy",
"args": ["-f", "docs/images/screenshot.png", "-O"],
"stopAtEntry": false,
"cwd": "${workspaceFolder}",
"environment": [
{
"name": "G_MESSAGES_DEBUG",
"value": "all"
}
],
"externalConsole": false,
"MIMode": "gdb",
"setupCommands": [
{
"description": "Enable pretty-printing for gdb",
"text": "-enable-pretty-printing",
"ignoreFailures": true
}
]
},
{
"name": "swappy - stdin",
"type": "cppdbg",
Expand Down
8 changes: 7 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,12 @@ Select a region and swappshot it:
swappy -g "$(slurp)"
```

Print final surface to stdout (useful to pipe with other tools):

```sh
grim -g "$(slurp)" - | swappy -f - -o - | pngquant -
```

Grab a swappshot from a specific window under Sway, using `swaymsg` and `jq`:

```sh
Expand Down Expand Up @@ -92,7 +98,7 @@ The following lines can be used as swappy's default:
- `Ctrl+Shift+z` or `Ctrl+y`: Redo
- `Ctrl+s`: Save to file (see man page)
- `Ctrl+c`: Copy to clipboard
- `Escape` or `q`: Quit swappy
- `Escape` or `q` or `Ctrl+w`: Quit swappy

## Limitations

Expand Down
5 changes: 4 additions & 1 deletion include/pixbuf.h
Original file line number Diff line number Diff line change
Expand Up @@ -2,4 +2,7 @@

#include "swappy.h"

void pixbuf_save_to_file(struct swappy_state *state);
GdkPixbuf *pixbuf_get_from_state(struct swappy_state *state);
void pixbuf_save_state_to_folder(GdkPixbuf *pixbuf, char *folder);
void pixbuf_save_to_file(GdkPixbuf *pixbuf, char *file);
void pixbuf_save_to_stdout(GdkPixbuf *pixbuf);
1 change: 1 addition & 0 deletions include/swappy.h
Original file line number Diff line number Diff line change
Expand Up @@ -191,6 +191,7 @@ struct swappy_state {
/* Options */
char *geometry_str;
char *file_str;
char *output_file;

struct swappy_box *geometry;

Expand Down
31 changes: 29 additions & 2 deletions src/application.c
Original file line number Diff line number Diff line change
Expand Up @@ -166,6 +166,19 @@ static void action_text_size_increase(struct swappy_state *state) {
update_ui_text_size_widget(state);
}

static void save_state_to_file_or_folder(struct swappy_state *state,
char *file) {
GdkPixbuf *pixbuf = pixbuf_get_from_state(state);

if (file == NULL) {
pixbuf_save_state_to_folder(pixbuf, state->config->save_dir);
} else {
pixbuf_save_to_file(pixbuf, file);
}

g_object_unref(pixbuf);
}

void brush_clicked_handler(GtkWidget *widget, struct swappy_state *state) {
switch_mode_to_brush(state);
}
Expand All @@ -187,6 +200,9 @@ void arrow_clicked_handler(GtkWidget *widget, struct swappy_state *state) {
}

void application_finish(struct swappy_state *state) {
if (state->output_file != NULL) {
save_state_to_file_or_folder(state, state->output_file);
}
paint_free_all(state);
buffer_free_all(state);
cairo_surface_destroy(state->cairo_surface);
Expand All @@ -201,7 +217,7 @@ void application_finish(struct swappy_state *state) {
}

void save_clicked_handler(GtkWidget *widget, struct swappy_state *state) {
pixbuf_save_to_file(state);
save_state_to_file_or_folder(state, NULL);
}

void clear_clicked_handler(GtkWidget *widget, struct swappy_state *state) {
Expand All @@ -225,11 +241,14 @@ void window_keypress_handler(GtkWidget *widget, GdkEventKey *event,
clipboard_copy_drawing_area_to_selection(state);
break;
case GDK_KEY_s:
pixbuf_save_to_file(state);
save_state_to_file_or_folder(state, NULL);
break;
case GDK_KEY_b:
action_toggle_painting_pane(state);
break;
case GDK_KEY_w:
gtk_main_quit();
break;
case GDK_KEY_z:
action_undo(state);
break;
Expand Down Expand Up @@ -652,6 +671,14 @@ bool application_init(struct swappy_state *state) {
.arg_data = &state->file_str,
.description = "Load a file at a specific path",
},
{
.long_name = "output-file",
.short_name = 'o',
.arg = G_OPTION_ARG_STRING,
.arg_data = &state->output_file,
.description = "Print the final surface to the given file when "
"exiting, use - to print to stdout",
},
{NULL}};

state->app = gtk_application_new("me.jtheoof.swappy",
Expand Down
38 changes: 34 additions & 4 deletions src/pixbuf.c
Original file line number Diff line number Diff line change
@@ -1,12 +1,19 @@
#include "pixbuf.h"

#include <gio/gunixoutputstream.h>

#include "notification.h"

void pixbuf_save_to_file(struct swappy_state *state) {
GdkPixbuf *pixbuf_get_from_state(struct swappy_state *state) {
guint width = gtk_widget_get_allocated_width(state->ui->area);
guint height = gtk_widget_get_allocated_height(state->ui->area);
GdkPixbuf *pixbuf =
gdk_pixbuf_get_from_surface(state->cairo_surface, 0, 0, width, height);

return pixbuf;
}

void pixbuf_save_state_to_folder(GdkPixbuf *pixbuf, char *folder) {
GError *error = NULL;

time_t current_time;
Expand All @@ -17,8 +24,7 @@ void pixbuf_save_to_file(struct swappy_state *state) {
c_time_string = ctime(&current_time);
c_time_string[strlen(c_time_string) - 1] = '\0';
char path[MAX_PATH];
snprintf(path, MAX_PATH, "%s/%s %s.png", state->config->save_dir, "Swappshot",
c_time_string);
snprintf(path, MAX_PATH, "%s/%s %s.png", folder, "Swappshot", c_time_string);
gdk_pixbuf_savev(pixbuf, path, "png", NULL, NULL, &error);

if (error != NULL) {
Expand All @@ -32,5 +38,29 @@ void pixbuf_save_to_file(struct swappy_state *state) {
snprintf(message, len, "%s%s", msg, path);
notification_send("Swappy", message);
g_free(message);
g_object_unref(pixbuf);
}

void pixbuf_save_to_stdout(GdkPixbuf *pixbuf) {
GOutputStream *out;
GError *error = NULL;

out = g_unix_output_stream_new(STDOUT_FILENO, TRUE);

gdk_pixbuf_save_to_stream(pixbuf, out, "png", NULL, &error);

if (error != NULL) {
g_warning("unable to save surface to stdout: %s", error->message);
g_error_free(error);
return;
}

g_object_unref(out);
}

void pixbuf_save_to_file(GdkPixbuf *pixbuf, char *file) {
if (g_strcmp0(file, "-") == 0) {
pixbuf_save_to_stdout(pixbuf);
} else {
pixbuf_save_to_file(pixbuf, file);
}
}
10 changes: 9 additions & 1 deletion swappy.1.scd
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,14 @@ to: *$HOME/Desktop*.
If set to *-*, read the file from standard input instead. This is grim
friendly.

*-o, --output-file <file>*
Print the final surface to *<file>* when exiting the application.

If set to *-*, prints the final surface to *stdout*.

Note that the *Save* button will save the image to the config *save_dir*
parameter, as described in the SYNOPSIS section.

# CONFIG FILE

The config file is located at *$XDG\_CONFIG\_HOME/swappy/config* or at
Expand Down Expand Up @@ -93,7 +101,7 @@ The following lines can be used as swappy's default:
- *Ctrl+Shift+z* or *Ctrl+y*: Redo
- *Ctrl+s*: Save to file (see man page)
- *Ctrl+c*: Copy to clipboard
- *Escape* or *q*: Quit swappy
- *Escape* or *q* or *Ctrl+w*: Quit swappy

# AUTHORS

Expand Down

0 comments on commit 60879b2

Please sign in to comment.