static void clipboard_got_from_guest(SpiceMainChannel *main, guint selection,
                                     guint type, const guchar *data, guint size,
                                     gpointer user_data)
{
    RunInfo *ri = user_data;
    SpiceGtkSessionPrivate *s = ri->self->priv;
    gchar *conv = NULL;

    g_return_if_fail(selection == ri->selection);

    SPICE_DEBUG("clipboard got data");

    if (atom2agent[ri->info].vdagent == VD_AGENT_CLIPBOARD_UTF8_TEXT) {
        /* on windows, gtk+ would already convert to LF endings, but
           not on unix */
        if (spice_main_agent_test_capability(s->main, VD_AGENT_CAP_GUEST_LINEEND_CRLF)) {
            GError *err = NULL;

            conv = spice_dos2unix((gchar*)data, size, &err);
            if (err) {
                g_warning("Failed to convert text line ending: %s", err->message);
                g_clear_error(&err);
                goto end;
            }

            size = strlen(conv);
        }

        gtk_selection_data_set_text(ri->selection_data, conv ?: (gchar*)data, size);
    } else {
示例#2
0
static void clipboard_owner_change(GtkClipboard        *clipboard,
                                   GdkEventOwnerChange *event,
                                   gpointer            user_data)
{
    g_return_if_fail(SPICE_IS_GTK_SESSION(user_data));

    SpiceGtkSession *self = user_data;
    SpiceGtkSessionPrivate *s = self->priv;
    int selection;

    selection = get_selection_from_clipboard(s, clipboard);
    g_return_if_fail(selection != -1);

    if (s->main == NULL)
        return;

    if (s->clip_grabbed[selection]) {
        s->clip_grabbed[selection] = FALSE;
        if (spice_main_agent_test_capability(s->main, VD_AGENT_CAP_CLIPBOARD_BY_DEMAND))
            spice_main_clipboard_selection_release(s->main, selection);
    }

    switch (event->reason) {
    case GDK_OWNER_CHANGE_NEW_OWNER:
        if (gtk_clipboard_get_owner(clipboard) == G_OBJECT(self))
            break;

        s->clipboard_by_guest[selection] = FALSE;
        s->clip_hasdata[selection] = TRUE;
        if (s->auto_clipboard_enable && !read_only(self))
            gtk_clipboard_request_targets(clipboard, clipboard_get_targets,
                                          weak_ref(G_OBJECT(self)));
        break;
    default:
        s->clip_hasdata[selection] = FALSE;
        break;
    }
}
示例#3
0
static void clipboard_get_targets(GtkClipboard *clipboard,
                                  GdkAtom *atoms,
                                  gint n_atoms,
                                  gpointer user_data)
{
    WeakRef *weakref = user_data;
    SpiceGtkSession *self = (SpiceGtkSession*)weakref->object;
    weak_unref(weakref);

    if (self == NULL)
        return;

    g_return_if_fail(SPICE_IS_GTK_SESSION(self));

    SpiceGtkSessionPrivate *s = self->priv;
    guint32 types[SPICE_N_ELEMENTS(atom2agent)];
    char *name;
    int a, m, t;
    int selection;

    if (s->main == NULL)
        return;

    selection = get_selection_from_clipboard(s, clipboard);
    g_return_if_fail(selection != -1);

    SPICE_DEBUG("%s:", __FUNCTION__);
    if (spice_util_get_debug()) {
        for (a = 0; a < n_atoms; a++) {
            name = gdk_atom_name(atoms[a]);
            SPICE_DEBUG(" \"%s\"", name);
            g_free(name);
        }
    }

    memset(types, 0, sizeof(types));
    for (a = 0; a < n_atoms; a++) {
        name = gdk_atom_name(atoms[a]);
        for (m = 0; m < SPICE_N_ELEMENTS(atom2agent); m++) {
            if (strcasecmp(name, atom2agent[m].xatom) != 0) {
                continue;
            }
            /* found match */
            for (t = 0; t < SPICE_N_ELEMENTS(atom2agent); t++) {
                if (types[t] == atom2agent[m].vdagent) {
                    /* type already in list */
                    break;
                }
                if (types[t] == 0) {
                    /* add type to empty slot */
                    types[t] = atom2agent[m].vdagent;
                    break;
                }
            }
            break;
        }
        g_free(name);
    }
    for (t = 0; t < SPICE_N_ELEMENTS(atom2agent); t++) {
        if (types[t] == 0) {
            break;
        }
    }
    if (!s->clip_grabbed[selection] && t > 0) {
        s->clip_grabbed[selection] = TRUE;

        if (spice_main_agent_test_capability(s->main, VD_AGENT_CAP_CLIPBOARD_BY_DEMAND))
            spice_main_clipboard_selection_grab(s->main, selection, types, t);
        /* Sending a grab causes the agent to do an impicit release */
        s->nclip_targets[selection] = 0;
    }
}
示例#4
0
gboolean clipboard_requestFromGuest(SpiceMainChannel *main, guint selection,
                                  guint type, gpointer user_data)
{                                 
    SPICE_DEBUG("CB: clipboard_requestFromGuest()");
    if (!enableClipboardToGuest) {
        SPICE_DEBUG("CB: enableClipboardToGuest set to false. Doing nothing.");
        return TRUE;
    }

    SpiceDisplay *display;
    SpiceDisplayPrivate *d;
    
    if (clipboardOwner != CB_OWNER_HOST) {
        SPICE_DEBUG("We do NOT have clipboard grabbed, so we won't send it.");
        return FALSE;
    }
    
    display = global_display();
    if (global_display() == NULL) {
        return FALSE;
    }

    d = SPICE_DISPLAY_GET_PRIVATE(display);
    if (d->main == NULL) {
        return FALSE;
    }

    //TODO check values as spice-gtk-session.
    gchar *data = (gchar *) hostClipboard;
    SPICE_DEBUG("CB: hostClipboard 0x%x\n", hostClipboard);

    if (hostClipboard != NULL) {
        SPICE_DEBUG("CB: hostClipboard contains %s\n", hostClipboard);
    }

    if (data == NULL ) {
        SPICE_DEBUG("CB: No supported Clipboard format available\n");
        return FALSE;
    }
        
    /* Transform format (line ending, etc) before sending */ 
    gint len = 0;
    gpointer conv = NULL;
    
    /* Our clipboard is not GTK but windows. So we positively have CRLF as line break.
       But it is our (client program) responsability to give the guest the format it wants.
    */
    if (spice_main_agent_test_capability(d->main, VD_AGENT_CAP_GUEST_LINEEND_CRLF)) {
        SPICE_DEBUG("CB: Host to Guest, changing line ending\n");
        len = strnlen(data, CB_SIZE);
        conv = spice_unix2dos((gchar*)data, len);
        SPICE_DEBUG("CB: Host to Guest, changing line ending: OK\n");
        len = strnlen(conv, CB_SIZE);
    } else {
        len = strnlen((const char *)data, CB_SIZE);
    }

    spice_main_clipboard_selection_notify(d->main, 
            VD_AGENT_CLIPBOARD_SELECTION_CLIPBOARD, 
            VD_AGENT_CLIPBOARD_UTF8_TEXT,
            conv ? conv : data, len);
onError:
    g_free(conv);
    return FALSE;
}