[client] spice: added clipboard callbacks to decouple spice from SDL

This commit is contained in:
Geoffrey McRae 2019-02-22 18:59:45 +11:00
parent 0dfa7425c1
commit 689a1de69b
3 changed files with 91 additions and 28 deletions

View File

@ -486,6 +486,27 @@ static inline const uint32_t mapScancode(SDL_Scancode scancode)
return ps2;
}
bool spiceClipboardNotice(const SpiceDataType type)
{
// we only support text data for now
return (type == SPICE_DATA_TEXT);
}
void spiceClipboardData(const SpiceDataType type, uint8_t * buffer, uint32_t size)
{
// dos2unix
uint8_t * p = buffer;
for(uint32_t i = 0; i < size; ++i)
{
uint8_t c = buffer[i];
if (c != '\r')
*p++ = c;
}
*p = '\0';
SDL_SetClipboardText((char *)buffer);
}
int eventFilter(void * userdata, SDL_Event * event)
{
static bool serverMode = false;
@ -951,6 +972,7 @@ int run()
if (params.useSpice)
{
spice_set_on_clipboard_cb(spiceClipboardNotice, spiceClipboardData);
if (!spice_connect(params.spiceHost, params.spicePort, ""))
{
DEBUG_ERROR("Failed to connect to spice server");

View File

@ -39,8 +39,6 @@ Place, Suite 330, Boston, MA 02111-1307 USA
#include <spice/protocol.h>
#include <spice/vd_agent.h>
#include <SDL2/SDL.h>
#include "messages.h"
#include "rsa.h"
@ -118,9 +116,12 @@ struct Spice
bool cbSupported;
bool cbSelection;
char *cbBuffer;
SpiceDataType cbType;
uint8_t * cbBuffer;
uint32_t cbRemain;
uint32_t cbSize;
SpiceClipboardNotice cbNoticeFn;
SpiceClipboardData cbDataFn;
};
// globals
@ -146,7 +147,7 @@ bool spice_on_inputs_channel_read();
bool spice_agent_process (uint32_t dataSize);
bool spice_agent_connect ();
bool spice_agent_send_caps(bool request);
bool spice_agent_on_clipboard();
void spice_agent_on_clipboard();
// thread safe read/write methods
bool spice_write_msg (struct SpiceChannel * channel, uint32_t type, const void * buffer, const ssize_t size);
@ -199,6 +200,12 @@ void spice_disconnect()
spice_disconnect_channel(&spice.scInputs);
spice.sessionID = 0;
if (spice.cbBuffer)
free(spice.cbBuffer);
spice.cbBuffer = NULL;
spice.cbRemain = 0;
spice.cbSize = 0;
}
// ============================================================================
@ -919,7 +926,7 @@ bool spice_agent_process(uint32_t dataSize)
spice.cbSize += r;
if (spice.cbRemain == 0)
return spice_agent_on_clipboard();
spice_agent_on_clipboard();
return true;
}
@ -1031,7 +1038,7 @@ bool spice_agent_process(uint32_t dataSize)
spice.cbSize = 0;
spice.cbRemain = remaining;
spice.cbBuffer = (char *)malloc(remaining);
spice.cbBuffer = (uint8_t *)malloc(remaining);
const uint32_t r = remaining > dataSize ? dataSize : remaining;
if (!spice_read_nl(&spice.scMain, spice.cbBuffer, r))
@ -1048,7 +1055,7 @@ bool spice_agent_process(uint32_t dataSize)
spice.cbSize += r;
if (spice.cbRemain == 0)
return spice_agent_on_clipboard();
spice_agent_on_clipboard();
return true;
}
@ -1074,8 +1081,19 @@ bool spice_agent_process(uint32_t dataSize)
// there is zero documentation on the types field, it might be a bitfield
// but for now we are going to assume it's not.
// for now we only support text
if (types[0] == VD_AGENT_CLIPBOARD_UTF8_TEXT)
switch(types[0])
{
case VD_AGENT_CLIPBOARD_UTF8_TEXT : spice.cbType = SPICE_DATA_TEXT; break;
case VD_AGENT_CLIPBOARD_IMAGE_PNG : spice.cbType = SPICE_DATA_PNG ; break;
case VD_AGENT_CLIPBOARD_IMAGE_BMP : spice.cbType = SPICE_DATA_BMP ; break;
case VD_AGENT_CLIPBOARD_IMAGE_TIFF: spice.cbType = SPICE_DATA_TIFF; break;
case VD_AGENT_CLIPBOARD_IMAGE_JPG : spice.cbType = SPICE_DATA_JPG ; break;
default:
DEBUG_WARN("Unknown clipboard data type: %u", types[0]);
return true;
}
if (spice.cbNoticeFn && spice.cbNoticeFn(spice.cbType))
{
if (spice.cbSelection)
{
@ -1085,7 +1103,7 @@ bool spice_agent_process(uint32_t dataSize)
}
VDAgentClipboardRequest req;
req.type = VD_AGENT_CLIPBOARD_UTF8_TEXT;
req.type = types[0];
if (!spice_agent_write_msg(VD_AGENT_CLIPBOARD_REQUEST, &req, sizeof(req)))
{
@ -1111,25 +1129,15 @@ bool spice_agent_process(uint32_t dataSize)
// ============================================================================
bool spice_agent_on_clipboard()
void spice_agent_on_clipboard()
{
// dos2unix
char * p = spice.cbBuffer;
for(uint32_t i = 0; i < spice.cbSize; ++i)
{
char c = spice.cbBuffer[i];
if (c != '\r')
*p++ = c;
}
*p = '\0';
SDL_SetClipboardText(spice.cbBuffer);
if (spice.cbDataFn)
spice.cbDataFn(spice.cbType, spice.cbBuffer, spice.cbSize);
free(spice.cbBuffer);
spice.cbBuffer = NULL;
spice.cbSize = 0;
spice.cbRemain = 0;
return true;
}
// ============================================================================
@ -1459,3 +1467,21 @@ bool spice_mouse_release(uint32_t button)
return spice_write_msg(&spice.scInputs, SPICE_MSGC_INPUTS_MOUSE_RELEASE, &msg, sizeof(msg));
}
// ============================================================================
bool spice_set_on_clipboard_cb(SpiceClipboardNotice cbNoticeFn, SpiceClipboardData cbDataFn)
{
if ((cbNoticeFn && !cbDataFn) || (cbDataFn && !cbNoticeFn))
{
DEBUG_ERROR("Clipboard callback notice and data callbacks must be specified");
return false;
}
spice.cbNoticeFn = cbNoticeFn;
spice.cbDataFn = cbDataFn;
return true;
}
// ============================================================================

View File

@ -21,10 +21,22 @@ Place, Suite 330, Boston, MA 02111-1307 USA
#include <stdbool.h>
#include <stdint.h>
typedef enum SpiceDataType
{
SPICE_DATA_TEXT,
SPICE_DATA_PNG,
SPICE_DATA_BMP,
SPICE_DATA_TIFF,
SPICE_DATA_JPG
}
SpiceDataType;
typedef bool (*SpiceClipboardNotice)(const SpiceDataType type);
typedef void (*SpiceClipboardData )(const SpiceDataType type, uint8_t * buffer, uint32_t size);
bool spice_connect(const char * host, const unsigned short port, const char * password);
void spice_disconnect();
bool spice_process();
bool spice_agent_process();
bool spice_ready();
bool spice_key_down (uint32_t code);
@ -34,3 +46,6 @@ bool spice_mouse_position(uint32_t x, uint32_t y);
bool spice_mouse_motion ( int32_t x, int32_t y);
bool spice_mouse_press (uint32_t button);
bool spice_mouse_release (uint32_t button);
/* events */
bool spice_set_on_clipboard_cb(SpiceClipboardNotice cbNoticeFn, SpiceClipboardData cbDataFn);