mirror of
https://github.com/jtheoof/swappy.git
synced 2024-08-16 18:20:45 +03:00
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:
parent
f967eb458a
commit
196f7f4dea
24
.vscode/launch.json
vendored
24
.vscode/launch.json
vendored
@ -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",
|
||||
|
@ -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
|
||||
|
||||
|
@ -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);
|
@ -191,6 +191,7 @@ struct swappy_state {
|
||||
/* Options */
|
||||
char *geometry_str;
|
||||
char *file_str;
|
||||
char *output_file;
|
||||
|
||||
struct swappy_box *geometry;
|
||||
|
||||
|
@ -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",
|
||||
|
38
src/pixbuf.c
38
src/pixbuf.c
@ -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(¤t_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);
|
||||
}
|
||||
}
|
10
swappy.1.scd
10
swappy.1.scd
@ -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
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user