Extend VNC protocol to let the client enable/disable the background.

svn path=/trunk/kdenetwork/krfb/; revision=202747
This commit is contained in:
Tim Jansen
2003-01-25 17:31:36 +00:00
parent 6adcc3aa08
commit 60f6e1f35e
6 changed files with 59 additions and 20 deletions

1
TODO
View File

@@ -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,

View File

@@ -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)
return;
disableBackgroundState = state;
DCOPRef ref("kdesktop", "KBackgroundIface"); DCOPRef ref("kdesktop", "KBackgroundIface");
ref.setDCOPClient(KApplication::dcopClient()); ref.setDCOPClient(KApplication::dcopClient());
ref.send("setBackgroundEnabled(bool)", bool(true)); 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);
} }

View File

@@ -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:

View File

@@ -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 */

View File

@@ -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

View File

@@ -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;
} }