mirror of
https://github.com/gnif/LookingGlass.git
synced 2024-11-14 21:17:54 +00:00
[client] spice: added clipboard callbacks to decouple spice from SDL
This commit is contained in:
parent
0dfa7425c1
commit
689a1de69b
3 changed files with 91 additions and 28 deletions
|
@ -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");
|
||||
|
|
|
@ -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;
|
||||
uint32_t cbRemain;
|
||||
uint32_t cbSize;
|
||||
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;
|
||||
}
|
||||
|
||||
// ============================================================================
|
||||
|
@ -1458,4 +1466,22 @@ bool spice_mouse_release(uint32_t button)
|
|||
msg.button_state = spice.mouse.buttonState;
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
// ============================================================================
|
|
@ -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);
|
||||
|
@ -33,4 +45,7 @@ bool spice_mouse_mode (bool server);
|
|||
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);
|
||||
bool spice_mouse_release (uint32_t button);
|
||||
|
||||
/* events */
|
||||
bool spice_set_on_clipboard_cb(SpiceClipboardNotice cbNoticeFn, SpiceClipboardData cbDataFn);
|
Loading…
Reference in a new issue