Exemple #1
0
static gboolean clipboard_request(SpiceMainChannel *main, guint selection,
                                  guint type, gpointer user_data)
{
    g_return_val_if_fail(SPICE_IS_GTK_SESSION(user_data), FALSE);

    SpiceGtkSession *self = user_data;
    SpiceGtkSessionPrivate *s = self->priv;
    GdkAtom atom;
    GtkClipboard* cb;
    int m;

    if (read_only(self))
        return FALSE;

    cb = get_clipboard_from_selection(s, selection);
    g_return_val_if_fail(cb != NULL, FALSE);

    for (m = 0; m < SPICE_N_ELEMENTS(atom2agent); m++) {
        if (atom2agent[m].vdagent == type)
            break;
    }

    g_return_val_if_fail(m < SPICE_N_ELEMENTS(atom2agent), FALSE);

    atom = gdk_atom_intern_static_string(atom2agent[m].xatom);
    gtk_clipboard_request_contents(cb, atom, clipboard_received_cb,
                                   weak_ref(G_OBJECT(self)));

    return TRUE;
}
Exemple #2
0
static gboolean clipboard_grab(SpiceMainChannel *main, guint selection,
                               guint32* types, guint32 ntypes,
                               gpointer user_data)
{
    g_return_val_if_fail(SPICE_IS_GTK_SESSION(user_data), FALSE);

    SpiceGtkSession *self = user_data;
    SpiceGtkSessionPrivate *s = self->priv;
    GtkTargetEntry targets[SPICE_N_ELEMENTS(atom2agent)];
    gboolean target_selected[SPICE_N_ELEMENTS(atom2agent)] = { FALSE, };
    gboolean found;
    GtkClipboard* cb;
    int m, n, i;

    cb = get_clipboard_from_selection(s, selection);
    g_return_val_if_fail(cb != NULL, FALSE);

    i = 0;
    for (n = 0; n < ntypes; ++n) {
        found = FALSE;
        for (m = 0; m < SPICE_N_ELEMENTS(atom2agent); m++) {
            if (atom2agent[m].vdagent == types[n] && !target_selected[m]) {
                found = TRUE;
                g_return_val_if_fail(i < SPICE_N_ELEMENTS(atom2agent), FALSE);
                targets[i].target = (gchar*)atom2agent[m].xatom;
                targets[i].flags = 0;
                targets[i].info = m;
                target_selected[m] = TRUE;
                i += 1;
            }
        }
        if (!found) {
            g_warning("clipboard: couldn't find a matching type for: %d",
                      types[n]);
        }
    }

    g_free(s->clip_targets[selection]);
    s->nclip_targets[selection] = i;
    s->clip_targets[selection] = g_memdup(targets, sizeof(GtkTargetEntry) * i);
    /* Receiving a grab implies we've released our own grab */
    s->clip_grabbed[selection] = FALSE;

    if (read_only(self) ||
        !s->auto_clipboard_enable ||
        s->nclip_targets[selection] == 0)
        goto skip_grab_clipboard;

    if (!gtk_clipboard_set_with_owner(cb, targets, i,
                                      clipboard_get, clipboard_clear, G_OBJECT(self))) {
        g_warning("clipboard grab failed");
        return FALSE;
    }
    s->clipboard_by_guest[selection] = TRUE;
    s->clip_hasdata[selection] = FALSE;

skip_grab_clipboard:
    return TRUE;
}
Exemple #3
0
static void clipboard_received_cb(GtkClipboard *clipboard,
                                  GtkSelectionData *selection_data,
                                  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;
    gint len = 0, m;
    guint32 type = VD_AGENT_CLIPBOARD_NONE;
    gchar* name;
    GdkAtom atom;
    int selection;

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

    len = gtk_selection_data_get_length(selection_data);
    if (len == -1) {
        SPICE_DEBUG("empty clipboard");
        len = 0;
    } else if (len == 0) {
        SPICE_DEBUG("TODO: what should be done here?");
    } else {
        atom = gtk_selection_data_get_data_type(selection_data);
        name = gdk_atom_name(atom);
        for (m = 0; m < SPICE_N_ELEMENTS(atom2agent); m++) {
            if (strcasecmp(name, atom2agent[m].xatom) == 0) {
                break;
            }
        }

        if (m >= SPICE_N_ELEMENTS(atom2agent)) {
            g_warning("clipboard_received for unsupported type: %s", name);
        } else {
            type = atom2agent[m].vdagent;
        }

        g_free(name);
    }

    spice_main_clipboard_selection_notify(s->main, selection, type,
        gtk_selection_data_get_data(selection_data), len);
}
Exemple #4
0
static const char * spice_log_level_to_string(SpiceLogLevel level)
{
#ifdef _MSC_VER
    /* MSVC++ does not implement C99 */
    static const char *to_string[] = {
         "ERROR",
         "CRITICAL",
         "Warning",
         "Info",
         "Debug"};
#else
    static const char *to_string[] = {
        [ SPICE_LOG_LEVEL_ERROR ] = "ERROR",
        [ SPICE_LOG_LEVEL_CRITICAL ] = "CRITICAL",
        [ SPICE_LOG_LEVEL_WARNING ] = "Warning",
        [ SPICE_LOG_LEVEL_INFO ] = "Info",
        [ SPICE_LOG_LEVEL_DEBUG ] = "Debug",
    };
#endif
    const char *str = NULL;
 
    if (level < SPICE_N_ELEMENTS(to_string)) {
        str = to_string[level];
    }

    return str;
}
Exemple #5
0
static void clipboard_get(GtkClipboard *clipboard,
                          GtkSelectionData *selection_data,
                          guint info, gpointer user_data)
{
    g_return_if_fail(SPICE_IS_GTK_SESSION(user_data));

    RunInfo ri = { NULL, };
    SpiceGtkSession *self = user_data;
    SpiceGtkSessionPrivate *s = self->priv;
    gulong clipboard_handler;
    gulong agent_handler;
    int selection;

    SPICE_DEBUG("clipboard get");

    selection = get_selection_from_clipboard(s, clipboard);
    g_return_if_fail(selection != -1);
    g_return_if_fail(info < SPICE_N_ELEMENTS(atom2agent));
    g_return_if_fail(s->main != NULL);

    ri.selection_data = selection_data;
    ri.info = info;
    ri.loop = g_main_loop_new(NULL, FALSE);
    ri.selection = selection;

    clipboard_handler = g_signal_connect(s->main, "main-clipboard-selection",
                                         G_CALLBACK(clipboard_got_from_guest),
                                         &ri);
    agent_handler = g_signal_connect(s->main, "notify::agent-connected",
                                     G_CALLBACK(clipboard_agent_connected),
                                     &ri);

    spice_main_clipboard_selection_request(s->main, selection,
                                           atom2agent[info].vdagent);

    /* apparently, this is needed to avoid dead-lock, from
       gtk_dialog_run */
    gdk_threads_leave();
    g_main_loop_run(ri.loop);
    gdk_threads_enter();

    g_main_loop_unref(ri.loop);
    ri.loop = NULL;
    g_signal_handler_disconnect(s->main, clipboard_handler);
    g_signal_handler_disconnect(s->main, agent_handler);
}
static void channel_destroy(SpiceSession *s, SpiceChannel *channel, gpointer data)
{
	__android_log_write(ANDROID_LOG_INFO, "android-spice", "channel_destroy called");

    spice_connection *conn = data;
    int id;

    g_object_get(channel, "channel-id", &id, NULL);
    if (SPICE_IS_MAIN_CHANNEL(channel)) {
        SPICE_DEBUG("zap main channel");
        conn->main = NULL;
    }

    if (SPICE_IS_DISPLAY_CHANNEL(channel)) {
        if (id >= SPICE_N_ELEMENTS(conn->wins))
            return;
        if (conn->wins[id] == NULL)
            return;
        SPICE_DEBUG("zap display channel (#%d)", id);
        destroy_spice_window(conn->wins[id]);
        conn->wins[id] = NULL;
    }

    if (SPICE_IS_PLAYBACK_CHANNEL(channel)) {
        SPICE_DEBUG("zap audio channel");
    }

    if (SPICE_IS_USBREDIR_CHANNEL(channel)) {
        __android_log_write(ANDROID_LOG_INFO, "android-spice", "Destroyed USB channel.");
        //update_auto_usbredir_sensitive(conn);
    }

    //if (SPICE_IS_PORT_CHANNEL(channel)) {
    //    if (SPICE_PORT_CHANNEL(channel) == stdin_port)
    //        stdin_port = NULL;
    //}
    conn->channels--;
    char buf[100];
    snprintf (buf, 100, "Number of channels: %d", conn->channels);
    __android_log_write(ANDROID_LOG_INFO, "android-spice", buf);
    if (conn->channels > 0) {
        return;
    }

    connection_destroy(conn);
}
static void spice_channel_constructed(GObject *gobject)
{
    SpiceChannel *channel = SPICE_CHANNEL(gobject);
    spice_channel *c = channel->priv;
    const char *desc = NULL;

    if (c->channel_type < SPICE_N_ELEMENTS(channel_desc))
        desc = channel_desc[c->channel_type];

    snprintf(c->name, sizeof(c->name), "%s-%d:%d",
             desc ? desc : "unknown", c->channel_type, c->channel_id);
    SPICE_DEBUG("%s: %s", c->name, __FUNCTION__);

    c->connection_id = spice_session_get_connection_id(c->session);
    spice_session_channel_new(c->session, channel);

    /* Chain up to the parent class */
    if (G_OBJECT_CLASS(spice_channel_parent_class)->constructed)
        G_OBJECT_CLASS(spice_channel_parent_class)->constructed(gobject);
}
void send_key(SpiceDisplay *display, int scancode, int down)
{
	SpiceDisplayPrivate *d = SPICE_DISPLAY_GET_PRIVATE(display);
    uint32_t i, b, m;

    if (!d->inputs)
        return;

    i = scancode / 32;
    b = scancode % 32;
    m = (1 << b);
    g_return_if_fail(i < SPICE_N_ELEMENTS(d->key_state));

    if (down) {
        spice_inputs_key_press(d->inputs, scancode);
        d->key_state[i] |= m;
    } else {
        if (!(d->key_state[i] & m)) {
            return;
        }
        spice_inputs_key_release(d->inputs, scancode);
        d->key_state[i] &= ~m;
    }
}
Exemple #9
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;
    }
}
RedClient::RedClient(Application& application)
    : RedChannel(*this, SPICE_CHANNEL_MAIN, 0, new MainChannelLoop(*this))
    , _application (application)
    , _port (-1)
    , _sport (-1)
    , _protocol (0)
    , _connection_id (0)
    , _mouse_mode (SPICE_MOUSE_MODE_SERVER)
    , _notify_disconnect (false)
    , _auto_display_res (false)
    , _agent_reply_wait_type (VD_AGENT_END_MESSAGE)
    , _aborting (false)
    , _msg_attach_channels_sent(false)
    , _agent_connected (false)
    , _agent_mon_config_sent (false)
    , _agent_disp_config_sent (false)
    , _agent_msg (new VDAgentMessage)
    , _agent_msg_data (NULL)
    , _agent_msg_pos (0)
    , _agent_out_msg (NULL)
    , _agent_out_msg_size (0)
    , _agent_out_msg_pos (0)
    , _agent_tokens (0)
    , _agent_timer (new AgentTimer(this))
    , _agent_caps_size(0)
    , _agent_caps(NULL)
    , _migrate (*this)
    , _glz_window (_glz_debug)
    , _during_migration (false)
{
    Platform::set_clipboard_listener(this);
    MainChannelLoop* message_loop = static_cast<MainChannelLoop*>(get_message_handler());
    uint32_t default_caps_size = SPICE_N_ELEMENTS(default_agent_caps);

    _agent_caps_size = VD_AGENT_CAPS_SIZE;
    ASSERT(VD_AGENT_CAPS_SIZE >= default_caps_size);
    _agent_caps = new uint32_t[_agent_caps_size];
    memcpy(_agent_caps, default_agent_caps, default_caps_size);
    message_loop->set_handler(SPICE_MSG_MIGRATE, &RedClient::handle_migrate);
    message_loop->set_handler(SPICE_MSG_SET_ACK, &RedClient::handle_set_ack);
    message_loop->set_handler(SPICE_MSG_PING, &RedClient::handle_ping);
    message_loop->set_handler(SPICE_MSG_WAIT_FOR_CHANNELS, &RedClient::handle_wait_for_channels);
    message_loop->set_handler(SPICE_MSG_DISCONNECTING, &RedClient::handle_disconnect);
    message_loop->set_handler(SPICE_MSG_NOTIFY, &RedClient::handle_notify);

    message_loop->set_handler(SPICE_MSG_MAIN_MIGRATE_BEGIN, &RedClient::handle_migrate_begin);
    message_loop->set_handler(SPICE_MSG_MAIN_MIGRATE_CANCEL, &RedClient::handle_migrate_cancel);
    message_loop->set_handler(SPICE_MSG_MAIN_MIGRATE_END, &RedClient::handle_migrate_end);
    message_loop->set_handler(SPICE_MSG_MAIN_MIGRATE_SWITCH_HOST,
                              &RedClient::handle_migrate_switch_host);
    message_loop->set_handler(SPICE_MSG_MAIN_INIT, &RedClient::handle_init);
    message_loop->set_handler(SPICE_MSG_MAIN_CHANNELS_LIST, &RedClient::handle_channels);
    message_loop->set_handler(SPICE_MSG_MAIN_MOUSE_MODE, &RedClient::handle_mouse_mode);
    message_loop->set_handler(SPICE_MSG_MAIN_MULTI_MEDIA_TIME, &RedClient::handle_mm_time);

    message_loop->set_handler(SPICE_MSG_MAIN_AGENT_CONNECTED, &RedClient::handle_agent_connected);
    message_loop->set_handler(SPICE_MSG_MAIN_AGENT_DISCONNECTED, &RedClient::handle_agent_disconnected);
    message_loop->set_handler(SPICE_MSG_MAIN_AGENT_DATA, &RedClient::handle_agent_data);
    message_loop->set_handler(SPICE_MSG_MAIN_AGENT_TOKEN, &RedClient::handle_agent_tokens);

    set_capability(SPICE_MAIN_CAP_SEMI_SEAMLESS_MIGRATE);
    start();
}
static void channel_new(SpiceSession *s, SpiceChannel *channel, gpointer data)
{
    spice_connection *conn = data;
    int id;

    g_object_get(channel, "channel-id", &id, NULL);
    conn->channels++;
    SPICE_DEBUG("new channel (#%d)", id);

    if (SPICE_IS_MAIN_CHANNEL(channel)) {
        SPICE_DEBUG("new main channel");
        conn->main = SPICE_MAIN_CHANNEL(channel);
        g_signal_connect(channel, "channel-event",
                         G_CALLBACK(main_channel_event), conn);
        //g_signal_connect(channel, "main-mouse-update",
        //                 G_CALLBACK(main_mouse_update), conn);
        //g_signal_connect(channel, "main-agent-update",
        //                 G_CALLBACK(main_agent_update), conn);
        //main_mouse_update(channel, conn);
        //main_agent_update(channel, conn);
    }

    if (SPICE_IS_DISPLAY_CHANNEL(channel)) {
        if (id >= SPICE_N_ELEMENTS(conn->wins))
            return;
        if (conn->wins[id] != NULL)
            return;
        SPICE_DEBUG("new display channel (#%d)", id);
        conn->wins[id] = create_spice_window(conn, channel, id);
        //g_signal_connect(channel, "display-mark",
        //                 G_CALLBACK(display_mark), conn->wins[id]);
        //update_auto_usbredir_sensitive(conn);
    }

    if (SPICE_IS_INPUTS_CHANNEL(channel)) {
        SPICE_DEBUG("new inputs channel");
        //g_signal_connect(channel, "inputs-modifiers",
        //                 G_CALLBACK(inputs_modifiers), conn);
    }

    if (soundEnabled && SPICE_IS_PLAYBACK_CHANNEL(channel)) {
        SPICE_DEBUG("new audio channel");
        conn->audio = spice_audio_get(s, NULL);
    }

    if (SPICE_IS_USBREDIR_CHANNEL(channel)) {
        __android_log_write(ANDROID_LOG_INFO, "android-spice", "Created USB channel, attempting to add devices");
        SpiceUsbDeviceManager *manager = spice_usb_device_manager_get(s, NULL);
        GPtrArray *devices = spice_usb_device_manager_get_devices(manager);
        if (devices) {
            for (int i = 0; i < devices->len; i++) {
                __android_log_write(ANDROID_LOG_INFO, "android-spicy", "Devices found, connecting...");
                usb_device_added(manager, g_ptr_array_index(devices, i), NULL);
            }
            g_ptr_array_unref(devices);
        }
    }

    //if (SPICE_IS_PORT_CHANNEL(channel)) {
    //    g_signal_connect(channel, "notify::port-opened",
    //                     G_CALLBACK(port_opened), conn);
    //    g_signal_connect(channel, "port-data",
    //                     G_CALLBACK(port_data), conn);
    //    spice_channel_connect(channel);
    //}
}