void spice_display_send_button(SpiceDisplay *display, int button, bool down) {
    SpiceDisplayPrivate *d = SPICE_DISPLAY_GET_PRIVATE(display);
    int button_mask;

    switch (button) {
    case SPICE_MOUSE_BUTTON_LEFT:
        button_mask = SPICE_MOUSE_BUTTON_MASK_LEFT;
        break;
    case SPICE_MOUSE_BUTTON_MIDDLE:
        button_mask = SPICE_MOUSE_BUTTON_MASK_MIDDLE;
        break;
    case SPICE_MOUSE_BUTTON_RIGHT:
        button_mask = SPICE_MOUSE_BUTTON_MASK_RIGHT;
        break;
    default:
        return;
    }

    if (down) {
        d->mouse_button_mask |= button_mask;
        if (d->inputs)
            spice_inputs_button_press(d->inputs, button, d->mouse_button_mask);
    } else {
        d->mouse_button_mask &= ~button_mask;
        if (d->inputs)
            spice_inputs_button_release(d->inputs, button,
                    d->mouse_button_mask);
    }
}
static void spice_display_init(SpiceDisplay *display)
{
    SpiceDisplayPrivate *d;

    d = display->priv = SPICE_DISPLAY_GET_PRIVATE(display);
    memset(d, 0, sizeof(*d));
}
JNIEXPORT void JNICALL
Java_com_iiordanov_aSPICE_SpiceCommunicator_UpdateBitmap (JNIEnv* env, jobject obj, jobject bitmap, gint x, gint y, gint width, gint height) {
	uchar* pixels;
    SpiceDisplayPrivate *d = SPICE_DISPLAY_GET_PRIVATE(global_display);

	if (AndroidBitmap_lockPixels(env, bitmap, (void**)&pixels) < 0) {
		__android_log_write(6, "android-io", "AndroidBitmap_lockPixels() failed!");
		return;
	}

	int slen = d->width * 4;
	int offset = (slen * y) + (x * 4);
	uchar *source = d->data;
	uchar *sourcepix = (uchar*) &source[offset];
	uchar *destpix   = (uchar*) &pixels[offset];

	for (int i = 0; i < height; i++) {
		for (int j = 0; j < width * 4; j += 4) {
			destpix[j + 0] = sourcepix[j + 2];
			destpix[j + 1] = sourcepix[j + 1];
			destpix[j + 2] = sourcepix[j + 0];
		}
		sourcepix = sourcepix + slen;
		destpix   = destpix + slen;
	}

	AndroidBitmap_unlockPixels(env, bitmap);
}
/**
 * spice_display_new:
 * @session: a #SpiceSession
 * @id: the display channel ID to associate with #SpiceDisplay
 *
 * Returns: a new #SpiceDisplay widget.
 **/
SpiceDisplay *spice_display_new(SpiceSession *session, int id)
{
    SpiceDisplay *display;
    SpiceDisplayPrivate *d;
    GList *list;
    GList *it;

    display = g_object_new(SPICE_TYPE_DISPLAY, NULL);
    d = SPICE_DISPLAY_GET_PRIVATE(display);
    d->session = g_object_ref(session);
    d->channel_id = id;
    SPICE_DEBUG("channel_id:%d",d->channel_id);

    g_signal_connect(session, "channel-new",
                     G_CALLBACK(channel_new), display);
    g_signal_connect(session, "channel-destroy",
                     G_CALLBACK(channel_destroy), display);
    list = spice_session_get_channels(session);
    for (it = g_list_first(list); it != NULL; it = g_list_next(it)) {
        channel_new(session, it->data, (gpointer*)display);
    }
    g_list_free(list);

    return display;
}
static void channel_destroy(SpiceSession *s, SpiceChannel *channel, gpointer data)
{
    SpiceDisplay *display = data;
    SpiceDisplayPrivate *d = SPICE_DISPLAY_GET_PRIVATE(display);
    int id;

    g_object_get(channel, "channel-id", &id, NULL);
    SPICE_DEBUG("channel_destroy %d", id);

    if (SPICE_IS_MAIN_CHANNEL(channel)) {
        disconnect_main(display);
        return;
    }

    if (SPICE_IS_DISPLAY_CHANNEL(channel)) {
        if (id != d->channel_id)
            return;
        disconnect_display(display);
        return;
    }

    if (SPICE_IS_CURSOR_CHANNEL(channel)) {
        if (id != d->channel_id)
            return;
        disconnect_cursor(display);
        return;
    }

    if (SPICE_IS_INPUTS_CHANNEL(channel)) {
        d->inputs = NULL;
        return;
    }
}
static void spice_display_dispose(GObject *obj)
{
    SpiceDisplay *display = SPICE_DISPLAY(obj);
    SpiceDisplayPrivate *d = SPICE_DISPLAY_GET_PRIVATE(display);

    SPICE_DEBUG("spice display dispose");

    disconnect_main(display);
    disconnect_display(display);
    //disconnect_cursor(display);

    //if (d->clipboard) {
    //    g_signal_handlers_disconnect_by_func(d->clipboard, G_CALLBACK(clipboard_owner_change),
    //                                         display);
    //    d->clipboard = NULL;
    //}

    //if (d->clipboard_primary) {
    //    g_signal_handlers_disconnect_by_func(d->clipboard_primary, G_CALLBACK(clipboard_owner_change),
    //                                         display);
    //    d->clipboard_primary = NULL;
    //}
    if (d->session) {
        g_signal_handlers_disconnect_by_func(d->session, G_CALLBACK(channel_new),
                                             display);
        g_signal_handlers_disconnect_by_func(d->session, G_CALLBACK(channel_destroy),
                                             display);
        g_object_unref(d->session);
        d->session = NULL;
    }
}
static void update_mouse_mode(SpiceChannel *channel, gpointer data)
{
    SpiceDisplay *display = data;
    SpiceDisplayPrivate *d = SPICE_DISPLAY_GET_PRIVATE(display);

    int mode;
    g_object_get(channel, "mouse-mode", &mode, NULL);
    uiCallbackMouseMode(d->ctx, mode == SPICE_MOUSE_MODE_CLIENT);
}
static void cursor_set(SpiceCursorChannel *cursor,
                       int w, int h,
                       int hot_x, int hot_y,
                       void *bitmap, void *data) {
    SpiceDisplay *display = data;
    SpiceDisplayPrivate *d = SPICE_DISPLAY_GET_PRIVATE(display);

    uiCallbackCursorConfig(d->ctx, true, bitmap, w, h, hot_x, hot_y);
}
static void disable_secondary_displays(SpiceMainChannel *channel, gpointer data) {
    __android_log_write(6, "android-spice", "disable_secondary_displays");

    SpiceDisplay *display = data;
    SpiceDisplayPrivate *d = SPICE_DISPLAY_GET_PRIVATE(display);

    spice_main_set_display_enabled(d->main, -1, FALSE);
    spice_main_set_display_enabled(d->main, 0, FALSE);
    spice_main_send_monitor_config(d->main);
}
static void channel_new(SpiceSession *s, SpiceChannel *channel, gpointer data)
{
    //__android_log_write(ANDROID_LOG_DEBUG, TAG, "channel_new");

    SpiceDisplay *display = data;
    SpiceDisplayPrivate *d = SPICE_DISPLAY_GET_PRIVATE(display);
    int id;

    g_object_get(channel, "channel-id", &id, NULL);
    if (SPICE_IS_MAIN_CHANNEL(channel)) {
        d->main = SPICE_MAIN_CHANNEL(channel);
        spice_g_signal_connect_object(channel, "main-mouse-update",
                                      G_CALLBACK(update_mouse_mode), display, 0);
        update_mouse_mode(channel, display);
        // TODO: For now, connect to this signal with a callback that disables
        // any secondary displays that crop up.
        g_signal_connect(channel, "main-agent-update",
                         G_CALLBACK(disable_secondary_displays), display);
        return;
    }

    if (SPICE_IS_DISPLAY_CHANNEL(channel)) {
        if (id != d->channel_id)
            return;
        d->display = channel;
        g_signal_connect(channel, "display-primary-create",
                         G_CALLBACK(primary_create), display);
        g_signal_connect(channel, "display-primary-destroy",
                         G_CALLBACK(primary_destroy), display);
        g_signal_connect(channel, "display-invalidate",
                         G_CALLBACK(invalidate), display);
        spice_channel_connect(channel);
        return;
    }

    if (SPICE_IS_CURSOR_CHANNEL(channel)) {
        if (id != d->channel_id)
            return;
        d->cursor = SPICE_CURSOR_CHANNEL(channel);
        g_signal_connect(channel, "cursor-set",
                         G_CALLBACK(cursor_set), display);
        g_signal_connect(channel, "cursor-hide",
                         G_CALLBACK(cursor_hide), display);
        g_signal_connect(channel, "cursor-reset",
                         G_CALLBACK(cursor_reset), display);
        spice_channel_connect(channel);
        return;
    }

    if (SPICE_IS_INPUTS_CHANNEL(channel)) {
        d->inputs = SPICE_INPUTS_CHANNEL(channel);
        spice_channel_connect(channel);
        return;
    }
}
void spice_display_send_scroll(SpiceDisplay *display, int button, int count) {
    SpiceDisplayPrivate *d = SPICE_DISPLAY_GET_PRIVATE(display);

    if (d->inputs) {
        for (int i = 0; i < count; i++) {
            spice_inputs_button_press(d->inputs, button, d->mouse_button_mask);
            spice_inputs_button_release(d->inputs, button,
                    d->mouse_button_mask);
        }
    }
}
static void spice_display_init(SpiceDisplay *display)
{
    global_display = display;
    SpiceDisplayPrivate *d;

    d = display->priv = SPICE_DISPLAY_GET_PRIVATE(display);
    memset(d, 0, sizeof(*d));
    d->have_mitshm = true;
    d->mouse_last_x = -1;
    d->mouse_last_y = -1;
}
gint get_display_id(SpiceDisplay *display)
{
    SpiceDisplayPrivate *d = SPICE_DISPLAY_GET_PRIVATE(display);

    /* supported monitor_id only with display channel #0 */
    if (d->channel_id == 0 && d->monitor_id >= 0)
        return d->monitor_id;

    g_return_val_if_fail(d->monitor_id <= 0, -1);

    return d->channel_id;
}
void spice_display_send_pointer(SpiceDisplay *display, bool absolute,
                                int x, int y) {
    SpiceDisplayPrivate *d = SPICE_DISPLAY_GET_PRIVATE(display);

    if (d->inputs) {
        if (absolute)
            spice_inputs_position(d->inputs, x, y, d->channel_id,
                    d->mouse_button_mask);
        else
            spice_inputs_motion(d->inputs, x, y, d->mouse_button_mask);
    }
}
static void disconnect_main(SpiceDisplay *display)
{
    SpiceDisplayPrivate *d = SPICE_DISPLAY_GET_PRIVATE(display);

    if (d->main == NULL)
        return;
    g_signal_handlers_disconnect_by_func(d->main, G_CALLBACK(update_mouse_mode),
                                         display);
    g_signal_handlers_disconnect_by_func(d->main, G_CALLBACK(disable_secondary_displays),
                                         display);
    d->main = NULL;
}
Example #16
0
JNIEXPORT void JNICALL
Java_com_iiordanov_aSPICE_SpiceCommunicator_UpdateBitmap (JNIEnv* env, jobject obj, jobject bitmap, gint x, gint y, gint width, gint height) {
	void* pixels;
    SpiceDisplayPrivate *d = SPICE_DISPLAY_GET_PRIVATE(global_display);

	if (AndroidBitmap_lockPixels(env, bitmap, &pixels) < 0) {
		__android_log_write(6, "android-io", "AndroidBitmap_lockPixels() failed!");
		return;
	}
	//__android_log_write(6, "android-io", "Copying new data into pixels.");
	updatePixels (pixels, d->data, x, y, width, height, d->width, d->height, 4);
	AndroidBitmap_unlockPixels(env, bitmap);
}
static void primary_destroy(SpiceChannel *channel, gpointer data) {
    SpiceDisplay *display = SPICE_DISPLAY(data);
    SpiceDisplayPrivate *d = SPICE_DISPLAY_GET_PRIVATE(display);

    //spicex_image_destroy(display);
    d->format = 0;
    d->width  = 0;
    d->height = 0;
    d->stride = 0;
    d->shmid  = 0;
    d->data   = 0;
    d->data_origin = 0;
}
void spice_display_request_resolution(SpiceDisplay *display, int w, int h) {
    SpiceDisplayPrivate *d = SPICE_DISPLAY_GET_PRIVATE(display);

    spice_main_update_display(d->main, get_display_id(display), 0, 0,
                              w, h, TRUE);
    spice_main_set_display_enabled(d->main, -1, TRUE);
    // TODO: Sending the monitor config right away may be causing guest OS to shut down.
    /*
    if (spice_main_send_monitor_config(d->main)) {
        __android_log_write(ANDROID_LOG_DEBUG, TAG, "Successfully sent monitor config");
    } else {
        __android_log_write(ANDROID_LOG_WARN, TAG, "Failed to send monitor config");
    }*/
}
static void disconnect_display(SpiceDisplay *display)
{
	SpiceDisplayPrivate *d = SPICE_DISPLAY_GET_PRIVATE(display);

    if (d->display == NULL)
        return;
    g_signal_handlers_disconnect_by_func(d->display, G_CALLBACK(primary_create),
                                         display);
    g_signal_handlers_disconnect_by_func(d->display, G_CALLBACK(primary_destroy),
                                         display);
    g_signal_handlers_disconnect_by_func(d->display, G_CALLBACK(invalidate),
                                         display);
    d->display = NULL;
}
static void disconnect_cursor(SpiceDisplay *display)
{
    SpiceDisplayPrivate *d = SPICE_DISPLAY_GET_PRIVATE(display);

    if (d->cursor == NULL)
        return;
    g_signal_handlers_disconnect_by_func(d->cursor, G_CALLBACK(cursor_set),
                                         display);
    g_signal_handlers_disconnect_by_func(d->cursor, G_CALLBACK(cursor_hide),
                                         display);
    g_signal_handlers_disconnect_by_func(d->cursor, G_CALLBACK(cursor_reset),
                                         display);
    d->cursor = NULL;
}
static void invalidate(SpiceChannel *channel,
                       gint x, gint y, gint w, gint h, gpointer data) {
    SpiceDisplay *display = data;

    if (!do_color_convert(display, x, y, w, h))
        return;

    SpiceDisplayPrivate *d = SPICE_DISPLAY_GET_PRIVATE(display);

	if (x + w > d->width || y + h > d->height) {
		__android_log_write(6, "android-spice", "Not drawing.");
	} else {
	    uiCallbackInvalidate (d, x, y, w, h);
	}
}
Example #22
0
static void primary_create(SpiceChannel *channel, gint format, gint width, gint height, gint stride, gint shmid, gpointer imgdata, gpointer data) {
	__android_log_write(6, "android-spice", "primary_create");

    SpiceDisplay *display = data;
    SpiceDisplayPrivate *d = SPICE_DISPLAY_GET_PRIVATE(display);

    d->format = format;
    d->stride = stride;
    d->shmid = shmid;
    d->width = width;
    d->height = height;
    d->data_origin = d->data = imgdata;

    uiCallbackSettingsChanged (0, width, height, 4);
}
JNIEXPORT void JNICALL
Java_com_iiordanov_aSPICE_SpiceCommunicator_SpiceRequestResolution(JNIEnv* env, jobject obj, jint x, jint y) {
    SpiceDisplay* display = global_display;
    SpiceDisplayPrivate *d = SPICE_DISPLAY_GET_PRIVATE(display);

    spice_main_update_display(d->main, get_display_id(display), 0, 0, x, y, TRUE);
    spice_main_set_display_enabled(d->main, -1, TRUE);
    // TODO: Sending the monitor config right away may be causing guest OS to shut down.
	/*
    if (spice_main_send_monitor_config(d->main)) {
        __android_log_write(6, "android-io", "Successfully sent monitor config");
    } else {
        __android_log_write(6, "android-io", "Failed to send monitor config");
    }*/
}
static void disconnect_main(SpiceDisplay *display)
{
	SpiceDisplayPrivate *d = SPICE_DISPLAY_GET_PRIVATE(display);
    //gint i;

    if (d->main == NULL)
        return;
    //g_signal_handlers_disconnect_by_func(d->main, G_CALLBACK(mouse_update),
    //                                     display);
    d->main = NULL;
    //for (i = 0; i < CLIPBOARD_LAST; ++i) {
    //    d->clipboard_by_guest[i] = FALSE;
    //    d->clip_grabbed[i] = FALSE;
    //    d->nclip_targets[i] = 0;
    //}
}
Example #25
0
JNIEXPORT void JNICALL
Java_com_iiordanov_aSPICE_SpiceCommunicator_SpiceKeyEvent(JNIEnv * env, jobject  obj, jboolean down, jint hardware_keycode) {
    SpiceDisplay* display = global_display;
    SpiceDisplayPrivate* d = SPICE_DISPLAY_GET_PRIVATE(display);

    SPICE_DEBUG("%s %s: keycode: %d", __FUNCTION__, "Key", hardware_keycode);

    if (!d->inputs)
    	return;

    if (down) {
        send_key(display, hardware_keycode, 1);
    } else {
		send_key(display, hardware_keycode, 0);
    }
}
JNIEXPORT void JNICALL
Java_com_iiordanov_aSPICE_SpiceCommunicator_SpiceButtonEvent(JNIEnv * env, jobject  obj, jint x, jint y, jint metaState, jint type) {
    SpiceDisplay* display = global_display;
    SpiceDisplayPrivate *d = SPICE_DISPLAY_GET_PRIVATE(display);
    //char buf[60];
    //snprintf (buf, 60, "Pointer event: %d at x: %d, y: %d", type, x, y);
    //__android_log_write(6, "android-io", buf);

    if (!d->inputs || (x >= 0 && x < d->width && y >= 0 && y < d->height)) {

		gboolean down = (type & PTRFLAGS_DOWN) != 0;
		int mouseButton = type &~ PTRFLAGS_DOWN;
		int newMask = update_mask (mouseButton, down);

		gint dx;
		gint dy;
	    switch (d->mouse_mode) {
	    case SPICE_MOUSE_MODE_CLIENT:
	        //__android_log_write(6, "android-io", "spice mouse mode client");
			spice_inputs_position(d->inputs, x, y, d->channel_id, newMask);
	        break;
	    case SPICE_MOUSE_MODE_SERVER:
	        //__android_log_write(6, "android-io", "spice mouse mode server");
	        dx = d->mouse_last_x != -1 ? x - d->mouse_last_x : 0;
	        dy = d->mouse_last_y != -1 ? y - d->mouse_last_y : 0;
	        spice_inputs_motion(d->inputs, dx, dy, newMask);
	        d->mouse_last_x = x;
	        d->mouse_last_y = y;
	        break;
	    default:
	        g_warn_if_reached();
	        break;
	    }

		if (mouseButton != SPICE_MOUSE_BUTTON_INVALID) {
			if (down) {
			    //__android_log_write(6, "android-io", "Button press");
				spice_inputs_button_press(d->inputs, mouseButton, newMask);
			} else {
			    //__android_log_write(6, "android-io", "Button release");
			    // This sleep is an ugly hack to prevent stuck buttons after a drag/drop gesture.
			    usleep(50000);
				spice_inputs_button_release(d->inputs, mouseButton, newMask);
			}
		}
    }
}
static gboolean do_color_convert(SpiceDisplay *display,
                                 gint x, gint y, gint w, gint h)
{
	SpiceDisplayPrivate *d = SPICE_DISPLAY_GET_PRIVATE(display);
    int i, j, maxy, maxx, miny, minx;
    guint32 *dest = d->data;
    guint16 *src = d->data_origin;

    if (!d->convert)
        return true;

    g_return_val_if_fail(d->format == SPICE_SURFACE_FMT_16_555 ||
                         d->format == SPICE_SURFACE_FMT_16_565, false);

    miny = MAX(y, 0);
    minx = MAX(x, 0);
    maxy = MIN(y + h, d->height);
    maxx = MIN(x + w, d->width);

    dest +=  (d->stride / 4) * miny;
    src += (d->stride / 2) * miny;

    if (d->format == SPICE_SURFACE_FMT_16_555) {
        for (j = miny; j < maxy; j++) {
            for (i = minx; i < maxx; i++) {
                dest[i] = CONVERT_0555_TO_0888(src[i]);
            }

            dest += d->stride / 4;
            src += d->stride / 2;
        }
    } else if (d->format == SPICE_SURFACE_FMT_16_565) {
        for (j = miny; j < maxy; j++) {
            for (i = minx; i < maxx; i++) {
                dest[i] = CONVERT_0565_TO_0888(src[i]);
            }

            dest += d->stride / 4;
            src += d->stride / 2;
        }
    }

    return true;
}
Example #28
0
static gboolean release_guest_clipboard(gpointer data)
{
    SpiceDisplay *display;
    SpiceDisplayPrivate *d;
    
    display = global_display();
    if (global_display() == NULL) {
        return FALSE;
    }

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

    spice_main_clipboard_selection_release(d->main, VD_AGENT_CLIPBOARD_SELECTION_CLIPBOARD);
    clipboardOwner = CB_OWNER_NONE;

    return FALSE;
}
static void primary_create(SpiceChannel *channel, gint format, gint width, gint height, gint stride, gint shmid, gpointer imgdata, gpointer data) {
	__android_log_write(6, "android-spice", "primary_create");

    SpiceDisplay *display = data;
    SpiceDisplayPrivate *d = SPICE_DISPLAY_GET_PRIVATE(display);

    // TODO: For now, don't do anything for secondary monitors
    if (get_display_id(display) > 0) {
        return;
    }

    d->format = format;
    d->stride = stride;
    d->shmid = shmid;
    d->width = width;
    d->height = height;
    d->data_origin = d->data = imgdata;

    uiCallbackSettingsChanged (0, width, height, 4);
}
void spice_display_copy_pixels(SpiceDisplay *display, uint32_t *dest,
                               int x, int y, int width, int height) {
    SpiceDisplayPrivate *d = SPICE_DISPLAY_GET_PRIVATE(display);
    uint32_t *source = d->data;
    uint32_t *sourcepix = &source[(d->width * y) + x];
    uint32_t *destpix   = &dest[(d->width * y) + x];

    //__android_log_print(ANDROID_LOG_DEBUG, TAG, "Drawing x: %d, y: %d, w: %d, h: %d, wBuf: %d, hBuf: %d", x, y, width, height, d->width, d->height);
    for (int i = 0; i < height; i++) {
        for (int j = 0; j < width; j++) {
            // ARGB -> R G B X
            uint32_t value = sourcepix[j] << 8;
#if BYTE_ORDER == LITTLE_ENDIAN
            value = __builtin_bswap32(value);
#endif
            destpix[j] = value;
        }
        sourcepix = sourcepix + d->width;
        destpix   = destpix + d->width;
    }
}