feat(application): print final surface to file or stdout

This allows a user to output the final surface to `stdout` using:

- `-0`
- `--output-file``

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

Closes #2
This commit is contained in:
Jeremy Attali 2020-01-19 18:09:15 -05:00
parent f967eb458a
commit 196f7f4dea
7 changed files with 108 additions and 9 deletions

24
.vscode/launch.json vendored
View File

@ -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",

View File

@ -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
@ -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

View File

@ -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);

View File

@ -191,6 +191,7 @@ struct swappy_state {
/* Options */
char *geometry_str;
char *file_str;
char *output_file;
struct swappy_box *geometry;

View File

@ -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);
}
@ -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);
@ -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) {
@ -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;
@ -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",

View File

@ -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;
@ -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) {
@ -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);
}
}

View File

@ -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
@ -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