Merge branch 'master' into KASM-1810_yaml_config
This commit is contained in:
@@ -234,6 +234,14 @@ void vncPointerMove(int x, int y)
|
||||
cursorPosY = y;
|
||||
}
|
||||
|
||||
void vncScroll(int x, int y) {
|
||||
ValuatorMask mask;
|
||||
valuator_mask_zero(&mask);
|
||||
valuator_mask_set(&mask, 2, x);
|
||||
valuator_mask_set(&mask, 3, y);
|
||||
QueuePointerEvents(vncPointerDev, MotionNotify, 0, POINTER_RELATIVE, &mask);
|
||||
}
|
||||
|
||||
void vncGetPointerPos(int *x, int *y)
|
||||
{
|
||||
if (vncPointerDev != NULL) {
|
||||
@@ -261,7 +269,7 @@ static int vncPointerProc(DeviceIntPtr pDevice, int onoff)
|
||||
* is not a bug.
|
||||
*/
|
||||
Atom btn_labels[BUTTONS];
|
||||
Atom axes_labels[2];
|
||||
Atom axes_labels[4];
|
||||
|
||||
switch (onoff) {
|
||||
case DEVICE_INIT:
|
||||
@@ -278,11 +286,29 @@ static int vncPointerProc(DeviceIntPtr pDevice, int onoff)
|
||||
|
||||
axes_labels[0] = XIGetKnownProperty(AXIS_LABEL_PROP_REL_X);
|
||||
axes_labels[1] = XIGetKnownProperty(AXIS_LABEL_PROP_REL_Y);
|
||||
axes_labels[2] = XIGetKnownProperty(AXIS_LABEL_PROP_REL_HSCROLL);
|
||||
axes_labels[3] = XIGetKnownProperty(AXIS_LABEL_PROP_REL_VSCROLL);
|
||||
|
||||
|
||||
InitPointerDeviceStruct(pDev, map, BUTTONS, btn_labels,
|
||||
(PtrCtrlProcPtr)NoopDDA,
|
||||
GetMotionHistorySize(),
|
||||
2, axes_labels);
|
||||
4, axes_labels);
|
||||
|
||||
InitValuatorAxisStruct(pDevice, 2, axes_labels[2], NO_AXIS_LIMITS, NO_AXIS_LIMITS, 0, 0, 0, Relative);
|
||||
InitValuatorAxisStruct(pDevice, 3, axes_labels[3], NO_AXIS_LIMITS, NO_AXIS_LIMITS, 0, 0, 0, Relative);
|
||||
|
||||
char* envScrollFactorH = getenv("SCROLL_FACTOR_H");
|
||||
char* envScrollFactorV = getenv("SCROLL_FACTOR_V");
|
||||
|
||||
float scrollFactorH = envScrollFactorH ? atof(envScrollFactorH) : 50.0;
|
||||
float scrollFactorV = envScrollFactorV ? atof(envScrollFactorV) : 50.0;
|
||||
|
||||
LOG_INFO("Mouse horizonatl scroll factor: %f", scrollFactorH);
|
||||
LOG_INFO("Mouse vertical scroll factor: %f", scrollFactorV);
|
||||
|
||||
SetScrollValuator(pDevice, 2, SCROLL_TYPE_HORIZONTAL, scrollFactorH, SCROLL_FLAG_NONE);
|
||||
SetScrollValuator(pDevice, 3, SCROLL_TYPE_VERTICAL, scrollFactorV, SCROLL_FLAG_PREFERRED);
|
||||
break;
|
||||
case DEVICE_ON:
|
||||
pDev->on = TRUE;
|
||||
|
||||
@@ -35,6 +35,7 @@ void vncInitInputDevice(void);
|
||||
void vncPointerButtonAction(int buttonMask, const unsigned char skipclick,
|
||||
const unsigned char skiprelease);
|
||||
void vncPointerMove(int x, int y);
|
||||
void vncScroll(int x, int y);
|
||||
void vncGetPointerPos(int *x, int *y);
|
||||
|
||||
void vncKeyboardEvent(KeySym keysym, unsigned xtcode, int down);
|
||||
|
||||
@@ -176,15 +176,6 @@ XserverDesktop::queryConnection(network::Socket* sock,
|
||||
return rfb::VNCServerST::PENDING;
|
||||
}
|
||||
|
||||
void XserverDesktop::requestClipboard()
|
||||
{
|
||||
try {
|
||||
server->requestClipboard();
|
||||
} catch (rdr::Exception& e) {
|
||||
vlog.error("XserverDesktop::requestClipboard: %s",e.str());
|
||||
}
|
||||
}
|
||||
|
||||
void XserverDesktop::announceClipboard(bool available)
|
||||
{
|
||||
try {
|
||||
@@ -194,12 +185,34 @@ void XserverDesktop::announceClipboard(bool available)
|
||||
}
|
||||
}
|
||||
|
||||
void XserverDesktop::sendClipboardData(const char* data)
|
||||
void XserverDesktop::clearBinaryClipboardData()
|
||||
{
|
||||
try {
|
||||
server->sendClipboardData(data);
|
||||
server->clearBinaryClipboardData();
|
||||
} catch (rdr::Exception& e) {
|
||||
vlog.error("XserverDesktop::sendClipboardData: %s",e.str());
|
||||
vlog.error("XserverDesktop::clearBinaryClipboardData: %s",e.str());
|
||||
}
|
||||
}
|
||||
|
||||
void XserverDesktop::sendBinaryClipboardData(const char* mime,
|
||||
const unsigned char *data,
|
||||
const unsigned len)
|
||||
{
|
||||
try {
|
||||
server->sendBinaryClipboardData(mime, data, len);
|
||||
} catch (rdr::Exception& e) {
|
||||
vlog.error("XserverDesktop::sendBinaryClipboardData: %s",e.str());
|
||||
}
|
||||
}
|
||||
|
||||
void XserverDesktop::getBinaryClipboardData(const char* mime,
|
||||
const unsigned char **data,
|
||||
unsigned *len)
|
||||
{
|
||||
try {
|
||||
server->getBinaryClipboardData(mime, data, len);
|
||||
} catch (rdr::Exception& e) {
|
||||
vlog.error("XserverDesktop::getBinaryClipboardData: %s",e.str());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -446,11 +459,14 @@ void XserverDesktop::approveConnection(uint32_t opaqueId, bool accept,
|
||||
|
||||
|
||||
void XserverDesktop::pointerEvent(const Point& pos, int buttonMask,
|
||||
const bool skipClick, const bool skipRelease)
|
||||
const bool skipClick, const bool skipRelease, int scrollX, int scrollY)
|
||||
{
|
||||
vncPointerMove(pos.x + vncGetScreenX(screenIndex),
|
||||
pos.y + vncGetScreenY(screenIndex));
|
||||
vncPointerButtonAction(buttonMask, skipClick, skipRelease);
|
||||
if (scrollX == 0 && scrollY == 0) {
|
||||
vncPointerMove(pos.x + vncGetScreenX(screenIndex), pos.y + vncGetScreenY(screenIndex));
|
||||
vncPointerButtonAction(buttonMask, skipClick, skipRelease);
|
||||
} else {
|
||||
vncScroll(scrollX, scrollY);
|
||||
}
|
||||
}
|
||||
|
||||
unsigned int XserverDesktop::setScreenLayout(int fb_width, int fb_height,
|
||||
@@ -469,19 +485,14 @@ unsigned int XserverDesktop::setScreenLayout(int fb_width, int fb_height,
|
||||
return ret;
|
||||
}
|
||||
|
||||
void XserverDesktop::handleClipboardRequest()
|
||||
{
|
||||
vncHandleClipboardRequest();
|
||||
}
|
||||
|
||||
void XserverDesktop::handleClipboardAnnounce(bool available)
|
||||
{
|
||||
vncHandleClipboardAnnounce(available);
|
||||
}
|
||||
|
||||
void XserverDesktop::handleClipboardData(const char* data_, int len)
|
||||
void XserverDesktop::handleClipboardAnnounceBinary(const unsigned num, const char mimes[][32])
|
||||
{
|
||||
vncHandleClipboardData(data_, len);
|
||||
vncHandleClipboardAnnounceBinary(num, mimes);
|
||||
}
|
||||
|
||||
void XserverDesktop::grabRegion(const rfb::Region& region)
|
||||
|
||||
@@ -62,7 +62,11 @@ public:
|
||||
void refreshScreenLayout();
|
||||
void requestClipboard();
|
||||
void announceClipboard(bool available);
|
||||
void sendClipboardData(const char* data);
|
||||
void clearBinaryClipboardData();
|
||||
void sendBinaryClipboardData(const char* mime, const unsigned char *data,
|
||||
const unsigned len);
|
||||
void getBinaryClipboardData(const char *mime, const unsigned char **ptr,
|
||||
unsigned *len);
|
||||
void bell();
|
||||
void setLEDState(unsigned int state);
|
||||
void setDesktopName(const char* name);
|
||||
@@ -90,13 +94,12 @@ public:
|
||||
|
||||
// rfb::SDesktop callbacks
|
||||
virtual void pointerEvent(const rfb::Point& pos, int buttonMask,
|
||||
const bool skipClick, const bool skipRelease);
|
||||
const bool skipClick, const bool skipRelease, int scrollX = 0, int scrollY = 0);
|
||||
virtual void keyEvent(rdr::U32 keysym, rdr::U32 keycode, bool down);
|
||||
virtual unsigned int setScreenLayout(int fb_width, int fb_height,
|
||||
const rfb::ScreenSet& layout);
|
||||
virtual void handleClipboardRequest();
|
||||
virtual void handleClipboardAnnounce(bool available);
|
||||
virtual void handleClipboardData(const char* data, int len);
|
||||
virtual void handleClipboardAnnounceBinary(const unsigned num, const char mimes[][32]);
|
||||
|
||||
// rfb::PixelBuffer callbacks
|
||||
virtual void grabRegion(const rfb::Region& r);
|
||||
|
||||
@@ -137,7 +137,7 @@ Send clipboard changes to clients. Default is on.
|
||||
.TP
|
||||
.B \-SendPrimary
|
||||
Send the primary selection and cut buffer to the server as well as the
|
||||
clipboard selection. Default is on.
|
||||
clipboard selection. Default is off.
|
||||
.
|
||||
.TP
|
||||
.B \-AcceptPointerEvents
|
||||
@@ -295,17 +295,22 @@ Allow click releases inside the blacked-out region.
|
||||
.
|
||||
.TP
|
||||
.B \-DLP_ClipSendMax \fIbytes\fP
|
||||
Limit clipboard bytes to send to clients in one transaction. Default 10,000.
|
||||
Limit clipboard bytes to send to clients in one transaction. Default 0.
|
||||
0 disables the limit, use \fBSendCutText\fP to disable clipboard sending entirely.
|
||||
.
|
||||
.TP
|
||||
.B \-DLP_ClipAcceptMax \fIbytes\fP
|
||||
Limit clipboard bytes to receive from clients in one transaction. Default 10,000.
|
||||
Limit clipboard bytes to receive from clients in one transaction. Default 0.
|
||||
0 disables the limit, use \fBAcceptCutText\fP to disable clipboard receiving entirely.
|
||||
.
|
||||
.TP
|
||||
.B \-DLP_ClipDelay \fIms\fP
|
||||
This many milliseconds must pass between clipboard actions. Default 1000.
|
||||
This many milliseconds must pass between clipboard actions. Default 0, 0 disables the limit.
|
||||
.
|
||||
.TP
|
||||
.B \-DLP_ClipTypes \fIa,b\fP
|
||||
Allowed binary clipboard mimetypes, separated by commas. Default
|
||||
chromium/x-web-custom-data,text/html,image/png
|
||||
.
|
||||
.TP
|
||||
.B \-DLP_KeyRateLimit \fIkeys-per-second\fP
|
||||
@@ -317,6 +322,10 @@ Log clipboard and keyboard actions. Info logs just clipboard direction and size,
|
||||
verbose adds the contents for both.
|
||||
.
|
||||
.TP
|
||||
.B \-selfBench
|
||||
Run a set of self-benchmarks and exit.
|
||||
.
|
||||
.TP
|
||||
.B \-noWebsocket
|
||||
Disable websockets and expose a traditional VNC port (5901, etc.).
|
||||
.
|
||||
|
||||
@@ -18,10 +18,12 @@
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <errno.h>
|
||||
|
||||
#include <set>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
#include <rfb/Configuration.h>
|
||||
#include <rfb/Logger_stdio.h>
|
||||
@@ -64,6 +66,8 @@ int vncFbstride[MAXSCREENS];
|
||||
|
||||
int vncInetdSock = -1;
|
||||
|
||||
static std::vector<dlp_mimetype_t> dlp_mimetypes;
|
||||
|
||||
struct CaseInsensitiveCompare {
|
||||
bool operator() (const std::string &a, const std::string &b) const {
|
||||
return strcasecmp(a.c_str(), b.c_str()) < 0;
|
||||
@@ -103,7 +107,7 @@ rfb::BoolParameter setPrimary("SetPrimary", "Set the PRIMARY as well "
|
||||
"as the CLIPBOARD selection", true);
|
||||
rfb::BoolParameter sendPrimary("SendPrimary",
|
||||
"Send the PRIMARY as well as the CLIPBOARD selection",
|
||||
true);
|
||||
false);
|
||||
|
||||
static PixelFormat vncGetPixelFormat(int scrIdx)
|
||||
{
|
||||
@@ -147,6 +151,38 @@ static void parseOverrideList(const char *text, ParamSet &out)
|
||||
}
|
||||
}
|
||||
|
||||
static void parseClipTypes()
|
||||
{
|
||||
char *str = strdup(Server::DLP_Clip_Types);
|
||||
char * const origstr = str;
|
||||
|
||||
while (1) {
|
||||
char *cur = strsep(&str, ",");
|
||||
if (!cur)
|
||||
break;
|
||||
if (!cur[0])
|
||||
continue;
|
||||
|
||||
// Hardcoded filters
|
||||
if (!strcmp(cur, "TEXT") ||
|
||||
!strcmp(cur, "STRING") ||
|
||||
strstr(cur, "text/plain") ||
|
||||
!strcmp(cur, "UTF8_STRING"))
|
||||
continue;
|
||||
|
||||
struct dlp_mimetype_t m;
|
||||
strncpy(m.mime, cur, sizeof(m.mime));
|
||||
m.mime[sizeof(m.mime) - 1] = '\0';
|
||||
|
||||
dlp_mimetypes.push_back(m);
|
||||
|
||||
vlog.debug("Adding DLP binary mime type %s", m.mime);
|
||||
}
|
||||
vlog.debug("Total %u binary mime types", dlp_mimetypes.size());
|
||||
|
||||
free(origstr);
|
||||
}
|
||||
|
||||
void vncExtensionInit(void)
|
||||
{
|
||||
if (vncExtGeneration == vncGetServerGeneration()) {
|
||||
@@ -163,6 +199,8 @@ void vncExtensionInit(void)
|
||||
|
||||
vncAddExtension();
|
||||
|
||||
if (!initialised)
|
||||
parseClipTypes();
|
||||
vncSelectionInit();
|
||||
|
||||
vlog.info("VNC extension running!");
|
||||
@@ -315,22 +353,30 @@ void vncUpdateDesktopName(void)
|
||||
desktop[scr]->setDesktopName(desktopName);
|
||||
}
|
||||
|
||||
void vncRequestClipboard(void)
|
||||
{
|
||||
for (int scr = 0; scr < vncGetScreenCount(); scr++)
|
||||
desktop[scr]->requestClipboard();
|
||||
}
|
||||
|
||||
void vncAnnounceClipboard(int available)
|
||||
{
|
||||
for (int scr = 0; scr < vncGetScreenCount(); scr++)
|
||||
desktop[scr]->announceClipboard(available);
|
||||
}
|
||||
|
||||
void vncSendClipboardData(const char* data)
|
||||
void vncSendBinaryClipboardData(const char* mime, const unsigned char *data,
|
||||
const unsigned len)
|
||||
{
|
||||
for (int scr = 0; scr < vncGetScreenCount(); scr++)
|
||||
desktop[scr]->sendClipboardData(data);
|
||||
desktop[scr]->sendBinaryClipboardData(mime, data, len);
|
||||
}
|
||||
|
||||
void vncGetBinaryClipboardData(const char *mime, const unsigned char **ptr,
|
||||
unsigned *len)
|
||||
{
|
||||
for (int scr = 0; scr < vncGetScreenCount(); scr++)
|
||||
desktop[scr]->getBinaryClipboardData(mime, ptr, len);
|
||||
}
|
||||
|
||||
void vncClearBinaryClipboardData()
|
||||
{
|
||||
for (int scr = 0; scr < vncGetScreenCount(); scr++)
|
||||
desktop[scr]->clearBinaryClipboardData();
|
||||
}
|
||||
|
||||
int vncConnectClient(const char *addr)
|
||||
@@ -486,3 +532,13 @@ int vncOverrideParam(const char *nameAndValue)
|
||||
|
||||
return rfb::Configuration::setParam(nameAndValue);
|
||||
}
|
||||
|
||||
unsigned dlp_num_mimetypes()
|
||||
{
|
||||
return dlp_mimetypes.size();
|
||||
}
|
||||
|
||||
const char *dlp_get_mimetype(const unsigned i)
|
||||
{
|
||||
return dlp_mimetypes[i].mime;
|
||||
}
|
||||
|
||||
@@ -45,6 +45,13 @@ int vncNotifyQueryConnect(void);
|
||||
extern void* vncFbptr[];
|
||||
extern int vncFbstride[];
|
||||
|
||||
struct dlp_mimetype_t {
|
||||
char mime[32];
|
||||
};
|
||||
|
||||
unsigned dlp_num_mimetypes();
|
||||
const char *dlp_get_mimetype(const unsigned i);
|
||||
|
||||
extern int vncInetdSock;
|
||||
|
||||
void vncExtensionInit(void);
|
||||
@@ -60,9 +67,12 @@ int vncGetSendPrimary(void);
|
||||
|
||||
void vncUpdateDesktopName(void);
|
||||
|
||||
void vncRequestClipboard(void);
|
||||
void vncAnnounceClipboard(int available);
|
||||
void vncSendClipboardData(const char* data);
|
||||
void vncClearBinaryClipboardData();
|
||||
void vncSendBinaryClipboardData(const char* mime, const unsigned char *data,
|
||||
const unsigned len);
|
||||
void vncGetBinaryClipboardData(const char *mime, const unsigned char **ptr,
|
||||
unsigned *len);
|
||||
|
||||
int vncConnectClient(const char *addr);
|
||||
|
||||
|
||||
@@ -43,6 +43,14 @@
|
||||
|
||||
static Atom xaPRIMARY, xaCLIPBOARD;
|
||||
static Atom xaTARGETS, xaTIMESTAMP, xaSTRING, xaTEXT, xaUTF8_STRING;
|
||||
static Atom xaINCR;
|
||||
static Atom *xaBinclips;
|
||||
static unsigned xaHtmlIndex, xaPngIndex;
|
||||
static Bool htmlPngPresent;
|
||||
|
||||
static unsigned *mimeIndexesFromClient;
|
||||
static unsigned numMimesFromClient;
|
||||
static Bool textFromClient;
|
||||
|
||||
static WindowPtr pWindow;
|
||||
static Window wid;
|
||||
@@ -66,8 +74,7 @@ static int vncCreateSelectionWindow(void);
|
||||
static int vncOwnSelection(Atom selection);
|
||||
static int vncConvertSelection(ClientPtr client, Atom selection,
|
||||
Atom target, Atom property,
|
||||
Window requestor, CARD32 time,
|
||||
const char* data, int len);
|
||||
Window requestor, CARD32 time);
|
||||
static int vncProcConvertSelection(ClientPtr client);
|
||||
static void vncSelectionRequest(Atom selection, Atom target);
|
||||
static int vncProcSendEvent(ClientPtr client);
|
||||
@@ -90,6 +97,32 @@ void vncSelectionInit(void)
|
||||
xaTEXT = MakeAtom("TEXT", 4, TRUE);
|
||||
xaUTF8_STRING = MakeAtom("UTF8_STRING", 11, TRUE);
|
||||
|
||||
xaINCR = MakeAtom("INCR", 4, TRUE);
|
||||
|
||||
unsigned i;
|
||||
mimeIndexesFromClient = calloc(dlp_num_mimetypes(), sizeof(unsigned));
|
||||
numMimesFromClient = 0;
|
||||
textFromClient = FALSE;
|
||||
xaBinclips = calloc(dlp_num_mimetypes(), sizeof(Atom));
|
||||
htmlPngPresent = FALSE;
|
||||
Bool htmlfound = FALSE, pngfound = FALSE;
|
||||
for (i = 0; i < dlp_num_mimetypes(); i++) {
|
||||
const char *cur = dlp_get_mimetype(i);
|
||||
xaBinclips[i] = MakeAtom(cur, strlen(cur), TRUE);
|
||||
|
||||
if (!strcmp(cur, "text/html")) {
|
||||
xaHtmlIndex = i;
|
||||
htmlfound = TRUE;
|
||||
}
|
||||
if (!strcmp(cur, "image/png")) {
|
||||
xaPngIndex = i;
|
||||
pngfound = TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
if (htmlfound && pngfound)
|
||||
htmlPngPresent = TRUE;
|
||||
|
||||
/* There are no hooks for when these are internal windows, so
|
||||
* override the relevant handlers. */
|
||||
origProcConvertSelection = ProcVector[X_ConvertSelection];
|
||||
@@ -103,7 +136,7 @@ void vncSelectionInit(void)
|
||||
FatalError("Add VNC ClientStateCallback failed\n");
|
||||
}
|
||||
|
||||
void vncHandleClipboardRequest(void)
|
||||
static void vncHandleClipboardRequest(void)
|
||||
{
|
||||
if (activeSelection == None) {
|
||||
LOG_DEBUG("Got request for local clipboard although no clipboard is active");
|
||||
@@ -161,24 +194,55 @@ void vncHandleClipboardAnnounce(int available)
|
||||
}
|
||||
}
|
||||
|
||||
void vncHandleClipboardData(const char* data, int len)
|
||||
void vncHandleClipboardAnnounceBinary(const unsigned num, const char mimes[][32])
|
||||
{
|
||||
struct VncDataTarget* next;
|
||||
|
||||
LOG_DEBUG("Got remote clipboard data, sending to X11 clients");
|
||||
|
||||
while (vncDataTargetHead != NULL) {
|
||||
if (num) {
|
||||
int rc;
|
||||
xEvent event;
|
||||
|
||||
rc = vncConvertSelection(vncDataTargetHead->client,
|
||||
vncDataTargetHead->selection,
|
||||
vncDataTargetHead->target,
|
||||
vncDataTargetHead->property,
|
||||
vncDataTargetHead->requestor,
|
||||
vncDataTargetHead->time,
|
||||
data, len);
|
||||
if (rc != Success) {
|
||||
LOG_DEBUG("Remote binary clipboard announced, grabbing local ownership");
|
||||
|
||||
if (vncGetSetPrimary()) {
|
||||
rc = vncOwnSelection(xaPRIMARY);
|
||||
if (rc != Success)
|
||||
LOG_ERROR("Could not set PRIMARY selection");
|
||||
}
|
||||
|
||||
rc = vncOwnSelection(xaCLIPBOARD);
|
||||
if (rc != Success)
|
||||
LOG_ERROR("Could not set CLIPBOARD selection");
|
||||
|
||||
unsigned i, valid = 0;
|
||||
for (i = 0; i < num; i++) {
|
||||
unsigned j;
|
||||
for (j = 0; j < dlp_num_mimetypes(); j++) {
|
||||
if (!strcmp(dlp_get_mimetype(j), mimes[i])) {
|
||||
mimeIndexesFromClient[valid] = j;
|
||||
valid++;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!strcmp(mimes[i], "text/plain"))
|
||||
textFromClient = TRUE;
|
||||
}
|
||||
numMimesFromClient = valid;
|
||||
LOG_DEBUG("Client sent %u mimes, %u were valid", num, valid);
|
||||
} else {
|
||||
struct VncDataTarget* next;
|
||||
numMimesFromClient = 0;
|
||||
textFromClient = FALSE;
|
||||
|
||||
if (pWindow == NULL)
|
||||
return;
|
||||
|
||||
LOG_DEBUG("Remote binary clipboard lost, removing local ownership");
|
||||
|
||||
DeleteWindowFromAnySelections(pWindow);
|
||||
|
||||
/* Abort any pending transfer */
|
||||
while (vncDataTargetHead != NULL) {
|
||||
xEvent event;
|
||||
|
||||
event.u.u.type = SelectionNotify;
|
||||
event.u.selectionNotify.time = vncDataTargetHead->time;
|
||||
event.u.selectionNotify.requestor = vncDataTargetHead->requestor;
|
||||
@@ -186,11 +250,11 @@ void vncHandleClipboardData(const char* data, int len)
|
||||
event.u.selectionNotify.target = vncDataTargetHead->target;
|
||||
event.u.selectionNotify.property = None;
|
||||
WriteEventsToClient(vncDataTargetHead->client, 1, &event);
|
||||
}
|
||||
|
||||
next = vncDataTargetHead->next;
|
||||
free(vncDataTargetHead);
|
||||
vncDataTargetHead = next;
|
||||
next = vncDataTargetHead->next;
|
||||
free(vncDataTargetHead);
|
||||
vncDataTargetHead = next;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -277,10 +341,22 @@ static int vncOwnSelection(Atom selection)
|
||||
return Success;
|
||||
}
|
||||
|
||||
static Bool clientHasBinaryAtom(const Atom target, unsigned *which)
|
||||
{
|
||||
unsigned i;
|
||||
for (i = 0; i < numMimesFromClient; i++) {
|
||||
if (xaBinclips[mimeIndexesFromClient[i]] == target) {
|
||||
*which = mimeIndexesFromClient[i];
|
||||
return TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
static int vncConvertSelection(ClientPtr client, Atom selection,
|
||||
Atom target, Atom property,
|
||||
Window requestor, CARD32 time,
|
||||
const char* data, int len)
|
||||
Window requestor, CARD32 time)
|
||||
{
|
||||
Selection *pSel;
|
||||
WindowPtr pWin;
|
||||
@@ -290,13 +366,8 @@ static int vncConvertSelection(ClientPtr client, Atom selection,
|
||||
|
||||
xEvent event;
|
||||
|
||||
if (data == NULL) {
|
||||
LOG_DEBUG("Selection request for %s (type %s)",
|
||||
NameForAtom(selection), NameForAtom(target));
|
||||
} else {
|
||||
LOG_DEBUG("Sending data for selection request for %s (type %s)",
|
||||
NameForAtom(selection), NameForAtom(target));
|
||||
}
|
||||
LOG_DEBUG("Selection request for %s (type %s)",
|
||||
NameForAtom(selection), NameForAtom(target));
|
||||
|
||||
rc = dixLookupSelection(&pSel, selection, client, DixGetAttrAccess);
|
||||
if (rc != Success)
|
||||
@@ -315,14 +386,23 @@ static int vncConvertSelection(ClientPtr client, Atom selection,
|
||||
realProperty = target;
|
||||
|
||||
/* FIXME: MULTIPLE target */
|
||||
unsigned binatomidx;
|
||||
|
||||
if (target == xaTARGETS) {
|
||||
Atom targets[] = { xaTARGETS, xaTIMESTAMP,
|
||||
xaSTRING, xaTEXT, xaUTF8_STRING };
|
||||
Atom targets[5 + numMimesFromClient];
|
||||
targets[0] = xaTARGETS;
|
||||
targets[1] = xaTIMESTAMP;
|
||||
targets[2] = xaSTRING;
|
||||
targets[3] = xaTEXT;
|
||||
targets[4] = xaUTF8_STRING;
|
||||
|
||||
unsigned i;
|
||||
for (i = 0; i < numMimesFromClient; i++)
|
||||
targets[5 + i] = xaBinclips[mimeIndexesFromClient[i]];
|
||||
|
||||
rc = dixChangeWindowProperty(serverClient, pWin, realProperty,
|
||||
XA_ATOM, 32, PropModeReplace,
|
||||
sizeof(targets)/sizeof(targets[0]),
|
||||
5 + numMimesFromClient,
|
||||
targets, TRUE);
|
||||
if (rc != Success)
|
||||
return rc;
|
||||
@@ -333,59 +413,47 @@ static int vncConvertSelection(ClientPtr client, Atom selection,
|
||||
TRUE);
|
||||
if (rc != Success)
|
||||
return rc;
|
||||
} else {
|
||||
if (data == NULL) {
|
||||
struct VncDataTarget* vdt;
|
||||
} else if (clientHasBinaryAtom(target, &binatomidx)) {
|
||||
const unsigned char *data;
|
||||
unsigned len;
|
||||
vncGetBinaryClipboardData(dlp_get_mimetype(binatomidx), &data, &len);
|
||||
rc = dixChangeWindowProperty(serverClient, pWin, realProperty,
|
||||
xaBinclips[binatomidx], 8, PropModeReplace,
|
||||
len, (unsigned char *) data, TRUE);
|
||||
if (rc != Success)
|
||||
return rc;
|
||||
} else if (textFromClient) {
|
||||
const unsigned char *data;
|
||||
unsigned len;
|
||||
vncGetBinaryClipboardData("text/plain", &data, &len);
|
||||
|
||||
if ((target != xaSTRING) && (target != xaTEXT) &&
|
||||
(target != xaUTF8_STRING))
|
||||
return BadMatch;
|
||||
|
||||
vdt = calloc(1, sizeof(struct VncDataTarget));
|
||||
if (vdt == NULL)
|
||||
if ((target == xaSTRING) || (target == xaTEXT)) {
|
||||
char* latin1;
|
||||
latin1 = vncUTF8ToLatin1(data, (size_t)-1);
|
||||
if (latin1 == NULL)
|
||||
return BadAlloc;
|
||||
|
||||
vdt->client = client;
|
||||
vdt->selection = selection;
|
||||
vdt->target = target;
|
||||
vdt->property = property;
|
||||
vdt->requestor = requestor;
|
||||
vdt->time = time;
|
||||
rc = dixChangeWindowProperty(serverClient, pWin, realProperty,
|
||||
XA_STRING, 8, PropModeReplace,
|
||||
len, latin1, TRUE);
|
||||
|
||||
vdt->next = vncDataTargetHead;
|
||||
vncDataTargetHead = vdt;
|
||||
vncStrFree(latin1);
|
||||
|
||||
LOG_DEBUG("Requesting clipboard data from client");
|
||||
|
||||
vncRequestClipboard();
|
||||
|
||||
return Success;
|
||||
if (rc != Success)
|
||||
return rc;
|
||||
} else if (target == xaUTF8_STRING) {
|
||||
rc = dixChangeWindowProperty(serverClient, pWin, realProperty,
|
||||
xaUTF8_STRING, 8, PropModeReplace,
|
||||
len, (char *) data, TRUE);
|
||||
if (rc != Success)
|
||||
return rc;
|
||||
} else {
|
||||
if ((target == xaSTRING) || (target == xaTEXT)) {
|
||||
char* latin1;
|
||||
|
||||
latin1 = vncUTF8ToLatin1(data, (size_t)-1);
|
||||
if (latin1 == NULL)
|
||||
return BadAlloc;
|
||||
|
||||
rc = dixChangeWindowProperty(serverClient, pWin, realProperty,
|
||||
XA_STRING, 8, PropModeReplace,
|
||||
len, latin1, TRUE);
|
||||
|
||||
vncStrFree(latin1);
|
||||
|
||||
if (rc != Success)
|
||||
return rc;
|
||||
} else if (target == xaUTF8_STRING) {
|
||||
rc = dixChangeWindowProperty(serverClient, pWin, realProperty,
|
||||
xaUTF8_STRING, 8, PropModeReplace,
|
||||
len, data, TRUE);
|
||||
if (rc != Success)
|
||||
return rc;
|
||||
} else {
|
||||
return BadMatch;
|
||||
}
|
||||
return BadMatch;
|
||||
}
|
||||
} else {
|
||||
LOG_ERROR("Text clipboard paste requested, but client sent no text");
|
||||
|
||||
return BadMatch;
|
||||
}
|
||||
|
||||
event.u.u.type = SelectionNotify;
|
||||
@@ -424,7 +492,7 @@ static int vncProcConvertSelection(ClientPtr client)
|
||||
pSel->window == wid) {
|
||||
rc = vncConvertSelection(client, stuff->selection,
|
||||
stuff->target, stuff->property,
|
||||
stuff->requestor, stuff->time, NULL, 0);
|
||||
stuff->requestor, stuff->time);
|
||||
if (rc != Success) {
|
||||
xEvent event;
|
||||
|
||||
@@ -483,6 +551,21 @@ static Bool vncHasAtom(Atom atom, const Atom list[], size_t size)
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
static Bool vncHasBinaryClipboardAtom(const Atom list[], size_t size)
|
||||
{
|
||||
size_t i, b;
|
||||
const unsigned num = dlp_num_mimetypes();
|
||||
|
||||
for (i = 0;i < size;i++) {
|
||||
for (b = 0; b < num; b++) {
|
||||
if (list[i] == xaBinclips[b])
|
||||
return TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
static void vncHandleSelection(Atom selection, Atom target,
|
||||
Atom property, Atom requestor,
|
||||
TimeStamp time)
|
||||
@@ -502,6 +585,9 @@ static void vncHandleSelection(Atom selection, Atom target,
|
||||
if (target != property)
|
||||
return;
|
||||
|
||||
if (prop->type == xaINCR)
|
||||
LOG_INFO("Incremental clipboard transfer denied, too large");
|
||||
|
||||
if (target == xaTARGETS) {
|
||||
if (prop->format != 32)
|
||||
return;
|
||||
@@ -510,16 +596,36 @@ static void vncHandleSelection(Atom selection, Atom target,
|
||||
|
||||
if (probing) {
|
||||
if (vncHasAtom(xaSTRING, (const Atom*)prop->data, prop->size) ||
|
||||
vncHasAtom(xaUTF8_STRING, (const Atom*)prop->data, prop->size)) {
|
||||
vncHasAtom(xaUTF8_STRING, (const Atom*)prop->data, prop->size) ||
|
||||
vncHasBinaryClipboardAtom((const Atom*)prop->data, prop->size)) {
|
||||
LOG_DEBUG("Compatible format found, notifying clients");
|
||||
vncClearBinaryClipboardData();
|
||||
activeSelection = selection;
|
||||
vncAnnounceClipboard(TRUE);
|
||||
vncHandleClipboardRequest();
|
||||
}
|
||||
} else {
|
||||
if (vncHasAtom(xaUTF8_STRING, (const Atom*)prop->data, prop->size))
|
||||
vncSelectionRequest(selection, xaUTF8_STRING);
|
||||
else if (vncHasAtom(xaSTRING, (const Atom*)prop->data, prop->size))
|
||||
vncSelectionRequest(selection, xaSTRING);
|
||||
|
||||
unsigned i;
|
||||
|
||||
Bool skiphtml = FALSE;
|
||||
if (htmlPngPresent &&
|
||||
vncHasAtom(xaBinclips[xaHtmlIndex], (const Atom*)prop->data, prop->size) &&
|
||||
vncHasAtom(xaBinclips[xaPngIndex], (const Atom*)prop->data, prop->size))
|
||||
skiphtml = TRUE;
|
||||
|
||||
for (i = 0; i < dlp_num_mimetypes(); i++) {
|
||||
if (skiphtml && i == xaHtmlIndex)
|
||||
continue;
|
||||
if (vncHasAtom(xaBinclips[i], (const Atom*)prop->data, prop->size)) {
|
||||
vncSelectionRequest(selection, xaBinclips[i]);
|
||||
//break;
|
||||
}
|
||||
}
|
||||
}
|
||||
} else if (target == xaSTRING) {
|
||||
char* filtered;
|
||||
@@ -539,10 +645,10 @@ static void vncHandleSelection(Atom selection, Atom target,
|
||||
if (utf8 == NULL)
|
||||
return;
|
||||
|
||||
LOG_DEBUG("Sending clipboard to clients (%d bytes)",
|
||||
LOG_DEBUG("Sending text part of binary clipboard to clients (%d bytes)",
|
||||
(int)strlen(utf8));
|
||||
|
||||
vncSendClipboardData(utf8);
|
||||
vncSendBinaryClipboardData("text/plain", utf8, strlen(utf8));
|
||||
|
||||
vncStrFree(utf8);
|
||||
} else if (target == xaUTF8_STRING) {
|
||||
@@ -557,12 +663,31 @@ static void vncHandleSelection(Atom selection, Atom target,
|
||||
if (filtered == NULL)
|
||||
return;
|
||||
|
||||
LOG_DEBUG("Sending clipboard to clients (%d bytes)",
|
||||
LOG_DEBUG("Sending text part of binary clipboard to clients (%d bytes)",
|
||||
(int)strlen(filtered));
|
||||
|
||||
vncSendClipboardData(filtered);
|
||||
vncSendBinaryClipboardData("text/plain", filtered, strlen(filtered));
|
||||
|
||||
vncStrFree(filtered);
|
||||
} else {
|
||||
unsigned i;
|
||||
|
||||
if (prop->format != 8)
|
||||
return;
|
||||
|
||||
for (i = 0; i < dlp_num_mimetypes(); i++) {
|
||||
if (target == xaBinclips[i]) {
|
||||
if (prop->type != xaBinclips[i])
|
||||
return;
|
||||
|
||||
LOG_DEBUG("Sending binary clipboard to clients (%d bytes)",
|
||||
prop->size);
|
||||
|
||||
vncSendBinaryClipboardData(dlp_get_mimetype(i), prop->data, prop->size);
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -24,9 +24,8 @@ extern "C" {
|
||||
|
||||
void vncSelectionInit(void);
|
||||
|
||||
void vncHandleClipboardRequest(void);
|
||||
void vncHandleClipboardAnnounce(int available);
|
||||
void vncHandleClipboardData(const char* data, int len);
|
||||
void vncHandleClipboardAnnounceBinary(const unsigned num, const char mimes[][32]);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user