feat(clipboard): use wl-copy if present

This commit is contained in:
Jeremy Attali 2020-01-05 22:34:16 -05:00
parent f48f36e7fe
commit 51b27d768e
2 changed files with 70 additions and 5 deletions

View File

@ -77,7 +77,7 @@ swappy -g "$(swaymsg -t get_tree | jq -r '.. | select(.pid? and .visible?) | .re
## Limitations
- **Copy**: Copy to clipboard won't work if you close swappy (the content of the clipboard is lost). This because GTK 3.24 [has not implemented persistent storage](https://gitlab.gnome.org/GNOME/gtk/blob/3.24.13/gdk/wayland/gdkdisplay-wayland.c#L857). We need to do it on the [Wayland level](https://github.com/swaywm/wlr-protocols/blob/master/unstable/wlr-data-control-unstable-v1.xml), or wait for GTK 4. For now, Paste your Swappshot where you want to before you close the app.
- **Copy**: If you don't have [wl-clipboard] installed, copy to clipboard won't work if you close swappy (the content of the clipboard is lost). This because GTK 3.24 [has not implemented persistent storage on wayland backend yet](https://gitlab.gnome.org/GNOME/gtk/blob/3.24.13/gdk/wayland/gdkdisplay-wayland.c#L857). We need to do it on the [Wayland level](https://github.com/swaywm/wlr-protocols/blob/master/unstable/wlr-data-control-unstable-v1.xml), or wait for GTK 4. For now, we use `wl-copy` if installed and revert to `gtk` clipboard if not found.
## Installation
@ -118,4 +118,5 @@ MIT
[slurp]: https://github.com/emersion/slurp
[grim]: https://github.com/emersion/grim
[sway]: https://github.com/swaywm/sway
[wl-clipboard]: https://github.com/bugaevc/wl-clipboard
[wlr-screencopy-unstable-v1]: https://github.com/swaywm/wlr-protocols/blob/master/unstable/wlr-screencopy-unstable-v1.xml

View File

@ -1,16 +1,80 @@
#include "clipboard.h"
#include <sys/types.h>
#include <sys/wait.h>
#include <unistd.h>
#include "notification.h"
#include "util.h"
#define gtk_clipboard_t GtkClipboard
#define gdk_pixbuf_t GdkPixbuf
static gboolean send_pixbuf_to_wl_copy(gdk_pixbuf_t *pixbuf) {
pid_t clipboard_process = 0;
int pipefd[2];
int status;
gsize size;
gchar *buffer = NULL;
GError *error = NULL;
if (pipe(pipefd) < 0) {
g_warning("unable to pipe for copy process to work");
return false;
}
clipboard_process = fork();
if (clipboard_process == -1) {
g_warning("unable to fork process for copy");
return false;
}
if (clipboard_process == 0) {
close(pipefd[1]);
dup2(pipefd[0], STDIN_FILENO);
close(pipefd[0]);
execlp("wl-copy", "wl-copy", NULL);
g_warning(
"Unable to copy contents to clipboard. Please make sure you have "
"`wl-clipboard`, `xclip`, or `xsel` installed.");
exit(1);
}
close(pipefd[0]);
gdk_pixbuf_save_to_buffer(pixbuf, &buffer, &size, "png", &error, NULL);
if (error != NULL) {
g_critical("unable to save pixbuf to buffer for copy: %s", error->message);
g_error_free(error);
return false;
}
write(pipefd[1], buffer, size);
close(pipefd[1]);
g_free(buffer);
waitpid(clipboard_process, &status, 0);
if (WIFEXITED(status)) {
return WEXITSTATUS(status) == 0; // Make sure the child exited properly
}
return false;
}
static void send_pixbuf_to_gdk_clipboard(gdk_pixbuf_t *pixbuf) {
gtk_clipboard_t *clipboard = gtk_clipboard_get(GDK_SELECTION_CLIPBOARD);
gtk_clipboard_set_image(clipboard, pixbuf);
gtk_clipboard_store(clipboard); // Does not work for Wayland gdk backend
}
bool clipboard_copy_drawing_area_to_selection(struct swappy_state *state) {
GtkClipboard *clipboard = gtk_clipboard_get(GDK_SELECTION_CLIPBOARD);
int width = gtk_widget_get_allocated_width(state->ui->area);
int height = gtk_widget_get_allocated_height(state->ui->area);
GdkPixbuf *pixbuf =
gdk_pixbuf_t *pixbuf =
gdk_pixbuf_get_from_surface(state->cairo_surface, 0, 0, width, height);
gtk_clipboard_set_image(clipboard, pixbuf);
gtk_clipboard_store(clipboard);
// Try `wl-copy` first and fall back to gtk function. See README.md.
if (!send_pixbuf_to_wl_copy(pixbuf)) {
send_pixbuf_to_gdk_clipboard(pixbuf);
}
char message[MAX_PATH];
snprintf(message, MAX_PATH, "Swappshot copied to clipboard\n");