mirror of
https://github.com/KDE/krfb
synced 2026-07-01 07:31:16 -07:00
Extend VNC protocol to let the client enable/disable the background.
svn path=/trunk/kdenetwork/krfb/; revision=202747
This commit is contained in:
1
TODO
1
TODO
@@ -2,7 +2,6 @@
|
|||||||
For 3.2:
|
For 3.2:
|
||||||
- write SLP service template for remote desktop protocols
|
- write SLP service template for remote desktop protocols
|
||||||
(documentation)
|
(documentation)
|
||||||
- extend VNC to enable/disable desktop wallpaper
|
|
||||||
- enhance RFB with SASL authentication (Kerberos)
|
- enhance RFB with SASL authentication (Kerberos)
|
||||||
- encrypted connections (using SASL and/or SSL/TLS)
|
- encrypted connections (using SASL and/or SSL/TLS)
|
||||||
- with kerberos/ssl: display name of remote user in connection dialog,
|
- with kerberos/ssl: display name of remote user in connection dialog,
|
||||||
|
|||||||
@@ -151,6 +151,11 @@ static void clientGoneHook(rfbClientPtr)
|
|||||||
self->handleClientGone();
|
self->handleClientGone();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void negotiationFinishedHook(rfbClientPtr cl)
|
||||||
|
{
|
||||||
|
self->handleNegotiationFinished(cl);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
void ConnectionDialog::closeEvent(QCloseEvent *)
|
void ConnectionDialog::closeEvent(QCloseEvent *)
|
||||||
@@ -311,6 +316,8 @@ void SessionEstablishedEvent::exec() {
|
|||||||
RFBController::RFBController(Configuration *c) :
|
RFBController::RFBController(Configuration *c) :
|
||||||
allowDesktopControl(false),
|
allowDesktopControl(false),
|
||||||
configuration(c),
|
configuration(c),
|
||||||
|
disableBackgroundPending(false),
|
||||||
|
disableBackgroundState(false),
|
||||||
closePending(false),
|
closePending(false),
|
||||||
forcedClose(false)
|
forcedClose(false)
|
||||||
{
|
{
|
||||||
@@ -370,9 +377,9 @@ void RFBController::startServer(int inetdFd, bool xtestGrab)
|
|||||||
|
|
||||||
if ( server->rfbServerFormat.bitsPerPixel == 8 ) {
|
if ( server->rfbServerFormat.bitsPerPixel == 8 ) {
|
||||||
server->rfbServerFormat.redShift = 0;
|
server->rfbServerFormat.redShift = 0;
|
||||||
server->rfbServerFormat.greenShift = 2;
|
server->rfbServerFormat.greenShift = 3;
|
||||||
server->rfbServerFormat.blueShift = 5;
|
server->rfbServerFormat.blueShift = 6;
|
||||||
server->rfbServerFormat.redMax = 3;
|
server->rfbServerFormat.redMax = 7;
|
||||||
server->rfbServerFormat.greenMax = 7;
|
server->rfbServerFormat.greenMax = 7;
|
||||||
server->rfbServerFormat.blueMax = 3;
|
server->rfbServerFormat.blueMax = 3;
|
||||||
} else {
|
} else {
|
||||||
@@ -485,6 +492,7 @@ void RFBController::refuseConnection()
|
|||||||
bool RFBController::checkAsyncEvents()
|
bool RFBController::checkAsyncEvents()
|
||||||
{
|
{
|
||||||
bool closed = false;
|
bool closed = false;
|
||||||
|
bool backgroundActionRequired = false;
|
||||||
asyncMutex.lock();
|
asyncMutex.lock();
|
||||||
VNCEvent *e;
|
VNCEvent *e;
|
||||||
for (e = asyncQueue.first(); e; e = asyncQueue.next())
|
for (e = asyncQueue.first(); e; e = asyncQueue.next())
|
||||||
@@ -495,17 +503,25 @@ bool RFBController::checkAsyncEvents()
|
|||||||
closed = true;
|
closed = true;
|
||||||
closePending = false;
|
closePending = false;
|
||||||
}
|
}
|
||||||
|
if (disableBackgroundPending != disableBackgroundState)
|
||||||
|
backgroundActionRequired = true;
|
||||||
asyncMutex.unlock();
|
asyncMutex.unlock();
|
||||||
|
|
||||||
|
if (backgroundActionRequired && (!closed) && !configuration->disableBackground())
|
||||||
|
disableBackground(disableBackgroundPending);
|
||||||
|
|
||||||
return closed;
|
return closed;
|
||||||
}
|
}
|
||||||
|
|
||||||
void RFBController::restoreBackground() {
|
void RFBController::disableBackground(bool state) {
|
||||||
if (configuration->disableBackground()) {
|
if (disableBackgroundState == state)
|
||||||
DCOPRef ref("kdesktop", "KBackgroundIface");
|
return;
|
||||||
ref.setDCOPClient(KApplication::dcopClient());
|
|
||||||
|
|
||||||
ref.send("setBackgroundEnabled(bool)", bool(true));
|
disableBackgroundState = state;
|
||||||
}
|
DCOPRef ref("kdesktop", "KBackgroundIface");
|
||||||
|
ref.setDCOPClient(KApplication::dcopClient());
|
||||||
|
|
||||||
|
ref.send("setBackgroundEnabled(bool)", bool(!state));
|
||||||
}
|
}
|
||||||
|
|
||||||
void RFBController::connectionClosed()
|
void RFBController::connectionClosed()
|
||||||
@@ -515,7 +531,7 @@ void RFBController::connectionClosed()
|
|||||||
.arg(remoteIp));
|
.arg(remoteIp));
|
||||||
|
|
||||||
idleTimer.stop();
|
idleTimer.stop();
|
||||||
restoreBackground();
|
disableBackground(false);
|
||||||
state = RFB_WAITING;
|
state = RFB_WAITING;
|
||||||
if (forcedClose)
|
if (forcedClose)
|
||||||
emit quitApp();
|
emit quitApp();
|
||||||
@@ -527,7 +543,7 @@ void RFBController::closeConnection()
|
|||||||
{
|
{
|
||||||
forcedClose = true;
|
forcedClose = true;
|
||||||
if (state == RFB_CONNECTED) {
|
if (state == RFB_CONNECTED) {
|
||||||
restoreBackground();
|
disableBackground(false);
|
||||||
|
|
||||||
if (!checkAsyncEvents()) {
|
if (!checkAsyncEvents()) {
|
||||||
asyncMutex.lock();
|
asyncMutex.lock();
|
||||||
@@ -571,7 +587,7 @@ void RFBController::idleSlot()
|
|||||||
defaultPtrAddEvent(0, p.x(),p.y(), server->rfbClientHead);
|
defaultPtrAddEvent(0, p.x(),p.y(), server->rfbClientHead);
|
||||||
asyncMutex.unlock();
|
asyncMutex.unlock();
|
||||||
|
|
||||||
checkAsyncEvents();
|
checkAsyncEvents(); // check 2nd time (see 3rd line)
|
||||||
}
|
}
|
||||||
|
|
||||||
void RFBController::dialogAccepted()
|
void RFBController::dialogAccepted()
|
||||||
@@ -657,6 +673,7 @@ bool RFBController::handleCheckPassword(rfbClientPtr cl,
|
|||||||
enum rfbNewClientAction RFBController::handleNewClient(rfbClientPtr cl)
|
enum rfbNewClientAction RFBController::handleNewClient(rfbClientPtr cl)
|
||||||
{
|
{
|
||||||
int socket = cl->sock;
|
int socket = cl->sock;
|
||||||
|
cl->negotiationFinishedHook = negotiationFinishedHook;
|
||||||
|
|
||||||
QString host, port;
|
QString host, port;
|
||||||
KSocketAddress *ksa = KExtendedSocket::peerAddress(socket);
|
KSocketAddress *ksa = KExtendedSocket::peerAddress(socket);
|
||||||
@@ -712,6 +729,13 @@ void RFBController::handleClientGone()
|
|||||||
asyncMutex.unlock();
|
asyncMutex.unlock();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void RFBController::handleNegotiationFinished(rfbClientPtr cl)
|
||||||
|
{
|
||||||
|
asyncMutex.lock();
|
||||||
|
disableBackgroundPending = cl->disableBackground;
|
||||||
|
asyncMutex.unlock();
|
||||||
|
}
|
||||||
|
|
||||||
void RFBController::handleKeyEvent(bool down, KeySym keySym) {
|
void RFBController::handleKeyEvent(bool down, KeySym keySym) {
|
||||||
if (!allowDesktopControl)
|
if (!allowDesktopControl)
|
||||||
return;
|
return;
|
||||||
@@ -747,12 +771,8 @@ void RFBController::sendKNotifyEvent(const QString &n, const QString &d)
|
|||||||
|
|
||||||
void RFBController::sendSessionEstablished()
|
void RFBController::sendSessionEstablished()
|
||||||
{
|
{
|
||||||
if (configuration->disableBackground()) {
|
if (configuration->disableBackground())
|
||||||
DCOPRef ref("kdesktop", "KBackgroundIface");
|
disableBackground(true);
|
||||||
ref.setDCOPClient(KApplication::dcopClient());
|
|
||||||
|
|
||||||
ref.send("setBackgroundEnabled(bool)", bool(false));
|
|
||||||
}
|
|
||||||
emit sessionEstablished(remoteIp);
|
emit sessionEstablished(remoteIp);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -138,6 +138,7 @@ public:
|
|||||||
void handlePointerEvent(int button_mask, int x, int y);
|
void handlePointerEvent(int button_mask, int x, int y);
|
||||||
enum rfbNewClientAction handleNewClient(rfbClientPtr cl);
|
enum rfbNewClientAction handleNewClient(rfbClientPtr cl);
|
||||||
void handleClientGone();
|
void handleClientGone();
|
||||||
|
void handleNegotiationFinished(rfbClientPtr cl);
|
||||||
int getPort();
|
int getPort();
|
||||||
void startServer(int inetdFd = -1, bool xtestGrab = true);
|
void startServer(int inetdFd = -1, bool xtestGrab = true);
|
||||||
|
|
||||||
@@ -160,7 +161,7 @@ private:
|
|||||||
void sendKNotifyEvent(const QString &name, const QString &desc);
|
void sendKNotifyEvent(const QString &name, const QString &desc);
|
||||||
bool checkAsyncEvents();
|
bool checkAsyncEvents();
|
||||||
void sendSessionEstablished();
|
void sendSessionEstablished();
|
||||||
void restoreBackground();
|
void disableBackground(bool state);
|
||||||
|
|
||||||
QString remoteIp;
|
QString remoteIp;
|
||||||
bool allowDesktopControl;
|
bool allowDesktopControl;
|
||||||
@@ -179,6 +180,8 @@ private:
|
|||||||
QMutex asyncMutex;
|
QMutex asyncMutex;
|
||||||
QPtrList<VNCEvent> asyncQueue;
|
QPtrList<VNCEvent> asyncQueue;
|
||||||
|
|
||||||
|
bool disableBackgroundPending; // background, as desired by libvncserver
|
||||||
|
bool disableBackgroundState; // real background state
|
||||||
bool closePending; // set when libvncserver detected close
|
bool closePending; // set when libvncserver detected close
|
||||||
bool forcedClose; // set when user closed connection
|
bool forcedClose; // set when user closed connection
|
||||||
private slots:
|
private slots:
|
||||||
|
|||||||
@@ -391,6 +391,7 @@ typedef struct sraRegion* sraRegionPtr;
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
typedef void (*ClientGoneHookPtr)(struct _rfbClientRec* cl);
|
typedef void (*ClientGoneHookPtr)(struct _rfbClientRec* cl);
|
||||||
|
typedef void (*NegotiationFinishedHookPtr)(struct _rfbClientRec* cl);
|
||||||
|
|
||||||
typedef struct _rfbClientRec {
|
typedef struct _rfbClientRec {
|
||||||
|
|
||||||
@@ -404,8 +405,12 @@ typedef struct _rfbClientRec {
|
|||||||
* This is useful if the IO functions have to behave client specific.
|
* This is useful if the IO functions have to behave client specific.
|
||||||
*/
|
*/
|
||||||
void* clientData;
|
void* clientData;
|
||||||
|
|
||||||
ClientGoneHookPtr clientGoneHook;
|
ClientGoneHookPtr clientGoneHook;
|
||||||
|
|
||||||
|
/* negotiationFinishedHook is called when the negotiation phase has ended */
|
||||||
|
NegotiationFinishedHookPtr negotiationFinishedHook;
|
||||||
|
|
||||||
SOCKET sock;
|
SOCKET sock;
|
||||||
char *host;
|
char *host;
|
||||||
|
|
||||||
@@ -526,6 +531,7 @@ typedef struct _rfbClientRec {
|
|||||||
|
|
||||||
Bool enableLastRectEncoding; /* client supports LastRect encoding */
|
Bool enableLastRectEncoding; /* client supports LastRect encoding */
|
||||||
Bool enableSoftCursorUpdates; /* client supports softcursor updates */
|
Bool enableSoftCursorUpdates; /* client supports softcursor updates */
|
||||||
|
Bool disableBackground; /* client wants to disable background */
|
||||||
Bool enableCursorShapeUpdates; /* client supports cursor shape updates */
|
Bool enableCursorShapeUpdates; /* client supports cursor shape updates */
|
||||||
Bool useRichCursorEncoding; /* rfbEncodingRichCursor is preferred */
|
Bool useRichCursorEncoding; /* rfbEncodingRichCursor is preferred */
|
||||||
Bool cursorWasChanged; /* cursor shape update should be sent */
|
Bool cursorWasChanged; /* cursor shape update should be sent */
|
||||||
|
|||||||
@@ -329,6 +329,7 @@ typedef struct {
|
|||||||
#define rfbEncodingSoftCursor 0xFFFFFF12
|
#define rfbEncodingSoftCursor 0xFFFFFF12
|
||||||
|
|
||||||
#define rfbEncodingLastRect 0xFFFFFF20
|
#define rfbEncodingLastRect 0xFFFFFF20
|
||||||
|
#define rfbEncodingBackground 0xFFFFFF25
|
||||||
|
|
||||||
#define rfbEncodingQualityLevel0 0xFFFFFFE0
|
#define rfbEncodingQualityLevel0 0xFFFFFFE0
|
||||||
#define rfbEncodingQualityLevel1 0xFFFFFFE1
|
#define rfbEncodingQualityLevel1 0xFFFFFFE1
|
||||||
|
|||||||
@@ -273,6 +273,7 @@ rfbNewTCPOrUDPClient(rfbScreen,sock,isUDP)
|
|||||||
cl->enableCursorShapeUpdates = FALSE;
|
cl->enableCursorShapeUpdates = FALSE;
|
||||||
cl->useRichCursorEncoding = FALSE;
|
cl->useRichCursorEncoding = FALSE;
|
||||||
cl->enableLastRectEncoding = FALSE;
|
cl->enableLastRectEncoding = FALSE;
|
||||||
|
cl->disableBackground = FALSE;
|
||||||
|
|
||||||
cl->compStreamInited = FALSE;
|
cl->compStreamInited = FALSE;
|
||||||
cl->compStream.total_in = 0;
|
cl->compStream.total_in = 0;
|
||||||
@@ -299,6 +300,7 @@ rfbNewTCPOrUDPClient(rfbScreen,sock,isUDP)
|
|||||||
|
|
||||||
cl->clientData = NULL;
|
cl->clientData = NULL;
|
||||||
cl->clientGoneHook = doNothingWithClient;
|
cl->clientGoneHook = doNothingWithClient;
|
||||||
|
cl->negotiationFinishedHook = doNothingWithClient;
|
||||||
switch (cl->screen->newClientHook(cl)) {
|
switch (cl->screen->newClientHook(cl)) {
|
||||||
case RFB_CLIENT_ON_HOLD:
|
case RFB_CLIENT_ON_HOLD:
|
||||||
cl->onHold = TRUE;
|
cl->onHold = TRUE;
|
||||||
@@ -663,6 +665,7 @@ rfbProcessClientNormalMessage(cl)
|
|||||||
cl->useCopyRect = FALSE;
|
cl->useCopyRect = FALSE;
|
||||||
cl->enableCursorShapeUpdates = FALSE;
|
cl->enableCursorShapeUpdates = FALSE;
|
||||||
cl->enableLastRectEncoding = FALSE;
|
cl->enableLastRectEncoding = FALSE;
|
||||||
|
cl->disableBackground = FALSE;
|
||||||
|
|
||||||
for (i = 0; i < msg.se.nEncodings; i++) {
|
for (i = 0; i < msg.se.nEncodings; i++) {
|
||||||
if ((n = ReadExact(cl, (char *)&enc, 4)) <= 0) {
|
if ((n = ReadExact(cl, (char *)&enc, 4)) <= 0) {
|
||||||
@@ -749,6 +752,11 @@ rfbProcessClientNormalMessage(cl)
|
|||||||
cl->enableLastRectEncoding = TRUE;
|
cl->enableLastRectEncoding = TRUE;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
case rfbEncodingBackground:
|
||||||
|
rfbLog("Disabling background for client "
|
||||||
|
"%s\n", cl->host);
|
||||||
|
cl->disableBackground = TRUE;
|
||||||
|
break;
|
||||||
#ifdef BACKCHANNEL
|
#ifdef BACKCHANNEL
|
||||||
case rfbEncodingBackChannel:
|
case rfbEncodingBackChannel:
|
||||||
if (!cl->enableBackChannel) {
|
if (!cl->enableBackChannel) {
|
||||||
@@ -780,6 +788,8 @@ rfbProcessClientNormalMessage(cl)
|
|||||||
cl->preferredEncoding = rfbEncodingRaw;
|
cl->preferredEncoding = rfbEncodingRaw;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
cl->negotiationFinishedHook(cl);
|
||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user