#ifdef HAVE_CONFIG_H #include #endif #include #include #include "lassi-server.h" #define LASSI_MARKER "application/x-mango-lassi-marker" static void targets_received(GtkClipboard *clipboard, GdkAtom *atoms, int n_atoms, gpointer userdata) { int j, k; LassiClipboardInfo *i = userdata; char **targets; g_assert(clipboard); g_assert(i); g_debug("recvd targs %p, %i", (void*) atoms, n_atoms); if (!atoms) return; targets = g_new0(char*, n_atoms+1); for (j = 0, k = 0; j < n_atoms; j++) { char *c = gdk_atom_name(atoms[j]); /* Avoid loops */ if (strcmp(c, LASSI_MARKER) == 0) { g_free(c); goto fail; } if (strcmp(c, "TIMESTAMP") == 0 || strcmp(c, "TARGETS") == 0 || strcmp(c, "CLIPBOARD_MANAGER") == 0 || strcmp(c, "CLIENT_WINDOW") == 0 || strcmp(c, "DELETE") == 0 || strcmp(c, "INSERT_PROPERTY") == 0 || strcmp(c, "INSERT_SELECTION") == 0 || strcmp(c, "LENGTH") == 0 || strcmp(c, "TASK") == 0 || strcmp(c, "MULTIPLE") == 0 || strcmp(c, "DRAWABLE") == 0) { g_free(c); continue; } targets[k++] = c; } g_debug("%p %i", (void*) targets, n_atoms); lassi_server_acquire_clipboard(i->server, clipboard == i->primary, targets); fail: g_strfreev(targets); } static void owner_change(GtkClipboard *clipboard, GdkEventOwnerChange *event, gpointer userdata) { LassiClipboardInfo *i = userdata; g_assert(clipboard); g_assert(i); g_debug("owner change"); if (event->reason == GDK_OWNER_CHANGE_NEW_OWNER) gtk_clipboard_request_targets(clipboard, targets_received, i); else lassi_server_return_clipboard(i->server, clipboard == i->primary); } static void get_func(GtkClipboard *clipboard, GtkSelectionData *sd, guint info, gpointer userdata) { LassiClipboardInfo *i = userdata; char *t; int f = 0; gpointer d = NULL; gint l = 0; g_assert(clipboard); g_assert(i); t = gdk_atom_name(sd->target); g_debug("get(%s)", t); if (lassi_server_get_clipboard(i->server, clipboard == i->primary, t, &f, &d, &l) >= 0) { g_debug("successfully got data"); gtk_selection_data_set(sd, sd->target, f, d, l); } else g_debug("failed to get data"); g_free(d); g_free(t); } static void clear_func(GtkClipboard *clipboard, gpointer userdata) { LassiClipboardInfo *i = userdata; g_assert(clipboard); g_assert(i); g_debug("clear"); gtk_clipboard_request_targets(clipboard, targets_received, i); } int lassi_clipboard_init(LassiClipboardInfo *i, LassiServer *s) { g_assert(i); g_assert(s); memset(i, 0, sizeof(*i)); i->server = s; i->clipboard = gtk_clipboard_get(GDK_SELECTION_CLIPBOARD); i->primary = gtk_clipboard_get(GDK_SELECTION_PRIMARY); g_signal_connect(i->clipboard, "owner_change", G_CALLBACK(owner_change), i); g_signal_connect(i->primary, "owner_change", G_CALLBACK(owner_change), i); return 0; } void lassi_clipboard_done(LassiClipboardInfo *i) { g_assert(i); memset(i, 0, sizeof(*i)); } void lassi_clipboard_set(LassiClipboardInfo *i, gboolean primary, char *targets[]) { int n = 0, j; gboolean b; char **t; GtkTargetEntry *e; for (t = targets; *t; t++) n++; e = g_new0(GtkTargetEntry, n+1); for (t = targets, j = 0; *t; t++, j++) { e[j].target = *t; e[j].info = j; } e[j].target = (char*) LASSI_MARKER; e[j].info = j; g_debug("setting %i targets", n+1); b = gtk_clipboard_set_with_data(primary ? i->primary : i->clipboard, e, n+1, get_func, clear_func, i); g_assert(b); } void lassi_clipboard_clear(LassiClipboardInfo *i, gboolean primary) { g_assert(i); gtk_clipboard_clear(primary ? i->primary : i->clipboard); } int lassi_clipboard_get(LassiClipboardInfo *i, gboolean primary, const char *target, int *f, gpointer *p, int *l) { GtkSelectionData*sd; g_assert(i); if (!(sd = gtk_clipboard_wait_for_contents(primary ? i->primary : i->clipboard, gdk_atom_intern(target, TRUE)))) return -1; g_assert(sd->length > 0); *f = sd->format; *p = g_memdup(sd->data, sd->length); *l = sd->length; gtk_selection_data_free(sd); return 0; }