Пример #1
0
void remmina_rdp_cliprdr_send_client_format_list(RemminaProtocolWidget *gp)
{
	TRACE_CALL(__func__);
	RemminaPluginRdpUiObject* ui;
	rfContext* rfi = GET_PLUGIN_DATA(gp);
	rfClipboard* clipboard;
	CLIPRDR_FORMAT_LIST *pFormatList;
	RemminaPluginRdpEvent rdp_event = { 0 };

	if (!rfi || !rfi->connected || rfi->is_reconnecting)
		return;

	clipboard = &(rfi->clipboard);

	ui = g_new0(RemminaPluginRdpUiObject, 1);
	ui->type = REMMINA_RDP_UI_CLIPBOARD;
	ui->clipboard.clipboard = clipboard;
	ui->clipboard.type = REMMINA_RDP_UI_CLIPBOARD_FORMATLIST;
	pFormatList = remmina_rdp_event_queue_ui_sync_retptr(gp, ui);

	rdp_event.type = REMMINA_RDP_EVENT_TYPE_CLIPBOARD_SEND_CLIENT_FORMAT_LIST;
	rdp_event.clipboard_formatlist.pFormatList = pFormatList;
	remmina_rdp_event_event_push(gp, &rdp_event);

}
Пример #2
0
static gboolean remmina_rdp_event_on_clipboard(GtkClipboard *clipboard, GdkEvent *event, RemminaProtocolWidget *gp)
{
	RemminaPluginRdpEvent rdp_event = { 0 };

	rdp_event.type = REMMINA_RDP_EVENT_TYPE_CLIPBOARD;
	remmina_rdp_event_event_push(gp, &rdp_event);

	return TRUE;
}
Пример #3
0
static gboolean remmina_rdp_event_on_motion(GtkWidget* widget, GdkEventMotion* event, RemminaProtocolWidget* gp)
{
	RemminaPluginRdpEvent rdp_event = { 0 };

	rdp_event.type = REMMINA_RDP_EVENT_TYPE_MOUSE;
	rdp_event.mouse_event.flags = PTR_FLAGS_MOVE;

	remmina_rdp_event_translate_pos(gp, event->x, event->y, &rdp_event.mouse_event.x, &rdp_event.mouse_event.y);
	remmina_rdp_event_event_push(gp, &rdp_event);

	return TRUE;
}
Пример #4
0
static gboolean remmina_rdp_event_on_button(GtkWidget* widget, GdkEventButton* event, RemminaProtocolWidget* gp)
{
	gint flag;
	RemminaPluginRdpEvent rdp_event = { 0 };

	/* We only accept 3 buttons */
	if ((event->button < 1) || (event->button > 3))
		return FALSE;

	/* We bypass 2button-press and 3button-press events */
	if ((event->type != GDK_BUTTON_PRESS) && (event->type != GDK_BUTTON_RELEASE))
		return TRUE;

	rdp_event.type = REMMINA_RDP_EVENT_TYPE_MOUSE;
	remmina_rdp_event_translate_pos(gp, event->x, event->y, &rdp_event.mouse_event.x, &rdp_event.mouse_event.y);

	flag = 0;

	if (event->type == GDK_BUTTON_PRESS)
		flag = PTR_FLAGS_DOWN;

	switch (event->button)
	{
		case 1:
			flag |= PTR_FLAGS_BUTTON1;
			break;
		case 2:
			flag |= PTR_FLAGS_BUTTON3;
			break;
		case 3:
			flag |= PTR_FLAGS_BUTTON2;
			break;
	}

	if (flag != 0)
	{
		rdp_event.mouse_event.flags = flag;
		remmina_rdp_event_event_push(gp, &rdp_event);
	}

	return TRUE;
}
Пример #5
0
static gboolean remmina_rdp_event_on_scroll(GtkWidget* widget, GdkEventScroll* event, RemminaProtocolWidget* gp)
{
	gint flag;
	RemminaPluginRdpEvent rdp_event = { 0 };

	flag = 0;
	rdp_event.type = REMMINA_RDP_EVENT_TYPE_MOUSE;

	switch (event->direction)
	{
		case GDK_SCROLL_UP:
			flag = PTR_FLAGS_WHEEL | 0x0078;
			break;

		case GDK_SCROLL_DOWN:
			flag = PTR_FLAGS_WHEEL | PTR_FLAGS_WHEEL_NEGATIVE | 0x0088;
			break;
		
#ifdef GDK_SCROLL_SMOOTH
		case GDK_SCROLL_SMOOTH:
			if (event->delta_y < 0)
				flag = PTR_FLAGS_WHEEL | 0x0078;
			if (event->delta_y > 0)
				flag = PTR_FLAGS_WHEEL | PTR_FLAGS_WHEEL_NEGATIVE | 0x0088;
			if (!flag)
				return FALSE;
			break;
#endif

		default:
			return FALSE;
	}

	rdp_event.mouse_event.flags = flag;
	remmina_rdp_event_translate_pos(gp, event->x, event->y, &rdp_event.mouse_event.x, &rdp_event.mouse_event.y);
	remmina_rdp_event_event_push(gp, &rdp_event);

	return TRUE;
}
Пример #6
0
static void remmina_rdp_event_release_key(RemminaProtocolWidget* gp, gint scancode)
{
	gint i, k;
	rfContext* rfi;
	RemminaPluginRdpEvent rdp_event = { 0 };

	rfi = GET_DATA(gp);
	rdp_event.type = REMMINA_RDP_EVENT_TYPE_SCANCODE;

	if (scancode == 0)
	{
		/* Send all release key events for previously pressed keys */
		rdp_event.key_event.up = True;

		for (i = 0; i < rfi->pressed_keys->len; i++)
		{
			rdp_event.key_event.key_code = g_array_index(rfi->pressed_keys, gint, i);
			remmina_rdp_event_event_push(gp, &rdp_event);
		}

		g_array_set_size(rfi->pressed_keys, 0);
	}
	else
	{
		/* Unregister the keycode only */
		for (i = 0; i < rfi->pressed_keys->len; i++)
		{
			k = g_array_index(rfi->pressed_keys, gint, i);

			if (k == scancode)
			{
				g_array_remove_index_fast(rfi->pressed_keys, i);
				break;
			}
		}
	}
}
Пример #7
0
static gboolean remmina_rdp_event_on_key(GtkWidget* widget, GdkEventKey* event, RemminaProtocolWidget* gp)
{
	GdkDisplay* display;
	guint16 cooked_keycode;
	rfContext* rfi;
	RemminaPluginRdpEvent rdp_event;

	rfi = GET_DATA(gp);
	rdp_event.type = REMMINA_RDP_EVENT_TYPE_SCANCODE;
	rdp_event.key_event.up = (event->type == GDK_KEY_PRESS ? False : True);
	rdp_event.key_event.extended = False;

	switch (event->keyval)
	{
		case GDK_KEY_Pause:
			rdp_event.key_event.key_code = 0x1D;
			rdp_event.key_event.up = False;
			remmina_rdp_event_event_push(gp, &rdp_event);
			rdp_event.key_event.key_code = 0x45;
			rdp_event.key_event.up = False;
			remmina_rdp_event_event_push(gp, &rdp_event);
			rdp_event.key_event.key_code = 0x1D;
			rdp_event.key_event.up = True;
			remmina_rdp_event_event_push(gp, &rdp_event);
			rdp_event.key_event.key_code = 0x45;
			rdp_event.key_event.up = True;
			remmina_rdp_event_event_push(gp, &rdp_event);
			break;

		default:
			if (!rfi->use_client_keymap)
			{
				rdp_event.key_event.key_code = freerdp_keyboard_get_rdp_scancode_from_x11_keycode(event->hardware_keycode);
				remmina_plugin_service->log_printf("[RDP]keyval=%04X keycode=%i scancode=%i extended=%i\n",
						event->keyval, event->hardware_keycode, rdp_event.key_event.key_code, &rdp_event.key_event.extended);
			}
			else
			{
				//TODO: Port to GDK functions
				display = gdk_display_get_default();
				cooked_keycode = XKeysymToKeycode(GDK_DISPLAY_XDISPLAY(display), XKeycodeToKeysym(GDK_DISPLAY_XDISPLAY(display), event->hardware_keycode, 0));
				rdp_event.key_event.key_code = freerdp_keyboard_get_rdp_scancode_from_x11_keycode(cooked_keycode);
				remmina_plugin_service->log_printf("[RDP]keyval=%04X raw_keycode=%i cooked_keycode=%i scancode=%i extended=%i\n",
						event->keyval, event->hardware_keycode, cooked_keycode, rdp_event.key_event.key_code, &rdp_event.key_event.extended);
			}

			if (rdp_event.key_event.key_code)
				remmina_rdp_event_event_push(gp, &rdp_event);

			break;
	}

	/* Register/unregister the pressed key */
	if (rdp_event.key_event.key_code)
	{
		if (event->type == GDK_KEY_PRESS)
			g_array_append_val(rfi->pressed_keys, rdp_event.key_event.key_code);
		else
			remmina_rdp_event_release_key(gp, rdp_event.key_event.key_code);
	}

	return TRUE;
}
Пример #8
0
void remmina_rdp_cliprdr_get_clipboard_data(RemminaProtocolWidget* gp, RemminaPluginRdpUiObject* ui)
{
	TRACE_CALL(__func__);
	GtkClipboard* gtkClipboard;
	UINT8* inbuf = NULL;
	UINT8* outbuf = NULL;
	GdkPixbuf *image = NULL;
	int size = 0;
	rfContext* rfi = GET_PLUGIN_DATA(gp);
	RemminaPluginRdpEvent rdp_event = { 0 };
	CLIPRDR_FORMAT_DATA_RESPONSE* pFormatDataResponse;

	gtkClipboard = gtk_widget_get_clipboard(rfi->drawing_area, GDK_SELECTION_CLIPBOARD);
	if (gtkClipboard) {
		switch (ui->clipboard.format) {
		case CF_TEXT:
		case CF_UNICODETEXT:
		case CB_FORMAT_HTML:
		{
			inbuf = (UINT8*)gtk_clipboard_wait_for_text(gtkClipboard);
			break;
		}

		case CB_FORMAT_PNG:
		case CB_FORMAT_JPEG:
		case CF_DIB:
		case CF_DIBV5:
		{
			image = gtk_clipboard_wait_for_image(gtkClipboard);
			break;
		}
		}
	}

	/* No data received, send nothing */
	if (inbuf != NULL || image != NULL) {
		switch (ui->clipboard.format) {
		case CF_TEXT:
		case CB_FORMAT_HTML:
		{
			size = strlen((char*)inbuf);
			outbuf = lf2crlf(inbuf, &size);
			break;
		}
		case CF_UNICODETEXT:
		{
			size = strlen((char*)inbuf);
			inbuf = lf2crlf(inbuf, &size);
			size = (ConvertToUnicode(CP_UTF8, 0, (CHAR*)inbuf, -1, (WCHAR**)&outbuf, 0) ) * sizeof(WCHAR);
			g_free(inbuf);
			break;
		}
		case CB_FORMAT_PNG:
		{
			gchar* data;
			gsize buffersize;
			gdk_pixbuf_save_to_buffer(image, &data, &buffersize, "png", NULL, NULL);
			outbuf = (UINT8*)malloc(buffersize);
			memcpy(outbuf, data, buffersize);
			size = buffersize;
			g_object_unref(image);
			break;
		}
		case CB_FORMAT_JPEG:
		{
			gchar* data;
			gsize buffersize;
			gdk_pixbuf_save_to_buffer(image, &data, &buffersize, "jpeg", NULL, NULL);
			outbuf = (UINT8*)malloc(buffersize);
			memcpy(outbuf, data, buffersize);
			size = buffersize;
			g_object_unref(image);
			break;
		}
		case CF_DIB:
		case CF_DIBV5:
		{
			gchar* data;
			gsize buffersize;
			gdk_pixbuf_save_to_buffer(image, &data, &buffersize, "bmp", NULL, NULL);
			size = buffersize - 14;
			outbuf = (UINT8*)malloc(size);
			memcpy(outbuf, data + 14, size);
			g_object_unref(image);
			break;
		}
		}
	}

	pFormatDataResponse = (CLIPRDR_FORMAT_DATA_RESPONSE*)malloc(sizeof(CLIPRDR_FORMAT_DATA_RESPONSE));
	if (!pFormatDataResponse) {
		if (outbuf) free(outbuf);
		return;
	}

	ZeroMemory(pFormatDataResponse, sizeof(CLIPRDR_FORMAT_DATA_RESPONSE));
	rdp_event.type = REMMINA_RDP_EVENT_TYPE_CLIPBOARD_SEND_CLIENT_FORMAT_DATA_RESPONSE;
	rdp_event.clipboard_formatdataresponse.pFormatDataResponse = pFormatDataResponse;
	pFormatDataResponse->msgFlags = CB_RESPONSE_OK;
	pFormatDataResponse->dataLen = size;
	pFormatDataResponse->requestedFormatData = outbuf;
	remmina_rdp_event_event_push(gp, &rdp_event);

}
Пример #9
0
void remmina_rdp_cliprdr_request_data(GtkClipboard *gtkClipboard, GtkSelectionData *selection_data, guint info, RemminaProtocolWidget* gp )
{
	TRACE_CALL(__func__);

	/* Called by GTK when someone press "Paste" on the client side.
	 * We ask to the server the data we need */

	CLIPRDR_FORMAT_DATA_REQUEST* pFormatDataRequest;
	rfClipboard* clipboard;
	rfContext* rfi = GET_PLUGIN_DATA(gp);
	RemminaPluginRdpEvent rdp_event = { 0 };
	struct timespec to;
	struct timeval tv;
	int rc;

	clipboard = &(rfi->clipboard);
	if ( clipboard->srv_clip_data_wait != SCDW_NONE ) {
		remmina_plugin_service->log_printf("[RDP] Cannot paste now, I’m transferring clipboard data from server. Try again later\n");
		return;
	}

	clipboard->format = info;

	/* Request Clipboard content from the server, the request is async */

	pthread_mutex_lock(&clipboard->transfer_clip_mutex);

	pFormatDataRequest = (CLIPRDR_FORMAT_DATA_REQUEST*)malloc(sizeof(CLIPRDR_FORMAT_DATA_REQUEST));
	ZeroMemory(pFormatDataRequest, sizeof(CLIPRDR_FORMAT_DATA_REQUEST));
	pFormatDataRequest->requestedFormatId = clipboard->format;
	clipboard->srv_clip_data_wait = SCDW_BUSY_WAIT;

	rdp_event.type = REMMINA_RDP_EVENT_TYPE_CLIPBOARD_SEND_CLIENT_FORMAT_DATA_REQUEST;
	rdp_event.clipboard_formatdatarequest.pFormatDataRequest = pFormatDataRequest;
	remmina_rdp_event_event_push(gp, &rdp_event);


	/* Busy wait clibpoard data for CLIPBOARD_TRANSFER_WAIT_TIME seconds */
	gettimeofday(&tv, NULL);
	to.tv_sec = tv.tv_sec + CLIPBOARD_TRANSFER_WAIT_TIME;
	to.tv_nsec = tv.tv_usec * 1000;
	rc = pthread_cond_timedwait(&clipboard->transfer_clip_cond, &clipboard->transfer_clip_mutex, &to);

	if ( rc == 0 ) {
		/* Data has arrived without timeout */
		if (clipboard->srv_data != NULL) {
			if (info == CB_FORMAT_PNG || info == CF_DIB || info == CF_DIBV5 || info == CB_FORMAT_JPEG) {
				gtk_selection_data_set_pixbuf(selection_data, clipboard->srv_data);
				g_object_unref(clipboard->srv_data);
			}else  {
				gtk_selection_data_set_text(selection_data, clipboard->srv_data, -1);
				free(clipboard->srv_data);
			}
		}
		clipboard->srv_clip_data_wait = SCDW_NONE;
	} else {
		clipboard->srv_clip_data_wait = SCDW_ASYNCWAIT;
		if ( rc == ETIMEDOUT ) {
			remmina_plugin_service->log_printf("[RDP] Clipboard data has not been transferred from the server in %d seconds. Try to paste later.\n",
				CLIPBOARD_TRANSFER_WAIT_TIME);
		}else  {
			remmina_plugin_service->log_printf("[RDP] internal error: pthread_cond_timedwait() returned %d\n", rc);
			clipboard->srv_clip_data_wait = SCDW_NONE;
		}
	}
	pthread_mutex_unlock(&clipboard->transfer_clip_mutex);

}