1
0
mirror of https://github.com/KDE/krfb synced 2026-07-01 07:41:17 -07:00

quite working

svn path=/trunk/kdenetwork/krfb/; revision=127687
This commit is contained in:
Tim Jansen
2001-12-18 01:57:19 +00:00
parent 8b085ac9b1
commit 0287dc9a83
8 changed files with 145 additions and 91 deletions

4
TODO
View File

@@ -1,2 +1,6 @@
Todo:
- fix what's-this help in dialogs
- remove help button?
Possible features:

View File

@@ -17,6 +17,7 @@
#include "trayicon.h"
#include "configuration.h"
#include "rfbcontroller.h"
#include <kpixmap.h>
#include <kaction.h>
@@ -50,6 +51,7 @@ int main(int argc, char *argv[])
KApplication app;
TrayIcon trayicon;
Configuration config;
RFBController controller(&config);
QObject::connect(&trayicon, SIGNAL(showConfigure()),
&config, SLOT(showDialog()));
@@ -57,5 +59,15 @@ int main(int argc, char *argv[])
QObject::connect(&app, SIGNAL(lastWindowClosed()),
&app, SLOT(quit()));
QObject::connect(&controller, SIGNAL(sessionEstablished()),
&trayicon, SLOT(openConnection()));
QObject::connect(&controller, SIGNAL(sessionFinished()),
&trayicon, SLOT(closeConnection()));
QObject::connect(&trayicon, SIGNAL(connectionClosed()),
&controller, SLOT(closeSession()));
QObject::connect(&config, SIGNAL(portChanged()),
&controller, SLOT(rebind()));
return app.exec();
}

View File

@@ -22,6 +22,7 @@
#include "rfbconnection.h"
#include <kdebug.h>
#include <qapplication.h>
#include <X11/Xutil.h>
#include <unistd.h>
@@ -29,25 +30,29 @@
#include <string.h>
RFBConnection::RFBConnection(Display *dpy, int fd, const QString &cpassword) :
RFBConnection::RFBConnection(Display *_dpy,
int _fd,
const QString &cpassword,
bool _allowInput) :
Server(),
dpy(dpy),
fd(fd),
dpy(_dpy),
fd(_fd),
allowInput(_allowInput),
buttonMask(0)
{
memcpy(password, "\0\0\0\0\0\0\0\0", 8);
if (!cpassword.isNull())
strncpy(password, cpassword.latin1(),
8 <= cpassword.length() ? 8 : cpassword.length());
(8 <= cpassword.length()) ? 8 : cpassword.length());
bufferedConnection = new BufferedConnection(32768, 32768);
connection = bufferedConnection;
InitBlocks(32, 32);
XTestGrabControl(dpy, true);
createFramebuffer();
InitBlocks(32, 32);
connection->send((unsigned char*) RFB_PROTOCOL_VERSION, 12);
}
@@ -62,6 +67,8 @@ RFBConnection::~RFBConnection() {
}
void RFBConnection::handleKeyEvent(KeyEvent &keyEvent) {
if (!allowInput)
return;
KeyCode kc = XKeysymToKeycode(dpy, keyEvent.key);
if (kc != NoSymbol)
XTestFakeKeyEvent(dpy,
@@ -71,6 +78,8 @@ void RFBConnection::handleKeyEvent(KeyEvent &keyEvent) {
}
void RFBConnection::handlePointerEvent(PointerEvent &pointerEvent) {
if (!allowInput)
return;
XTestFakeMotionEvent(dpy,
0,
pointerEvent.x_position,
@@ -97,48 +106,50 @@ void RFBConnection::createFramebuffer()
QApplication::desktop()->height(),
AllPlanes,
ZPixmap);
framebuffer.width = framebufferImage->width;
framebuffer.height = framebufferImage->height;
framebuffer.bytesPerLine = framebufferImage->bytes_per_line;
framebuffer.data = (unsigned char*) framebufferImage->data;
framebuffer = new Framebuffer();
framebuffer->width = framebufferImage->width;
framebuffer->height = framebufferImage->height;
framebuffer->bytesPerLine = framebufferImage->bytes_per_line;
framebuffer->data = (unsigned char*) framebufferImage->data;
framebuffer.pixelFormat.bits_per_pixel =
framebuffer->pixelFormat.bits_per_pixel =
framebufferImage->bits_per_pixel;
framebuffer.pixelFormat.depth = framebufferImage->depth;
framebuffer.pixelFormat.big_endian_flag =
framebuffer->pixelFormat.depth = framebufferImage->depth;
framebuffer->pixelFormat.big_endian_flag =
(framebufferImage->bitmap_bit_order == MSBFirst);
framebuffer.pixelFormat.true_colour_flag = true;
framebuffer->pixelFormat.true_colour_flag = true;
if (framebuffer.pixelFormat.bits_per_pixel == 8) {
framebuffer.pixelFormat.red_shift = 0;
framebuffer.pixelFormat.green_shift = 2;
framebuffer.pixelFormat.blue_shift = 5;
framebuffer.pixelFormat.red_max = 3;
framebuffer.pixelFormat.green_max = 7;
framebuffer.pixelFormat.blue_max = 3;
if (framebuffer->pixelFormat.bits_per_pixel == 8) {
framebuffer->pixelFormat.red_shift = 0;
framebuffer->pixelFormat.green_shift = 2;
framebuffer->pixelFormat.blue_shift = 5;
framebuffer->pixelFormat.red_max = 3;
framebuffer->pixelFormat.green_max = 7;
framebuffer->pixelFormat.blue_max = 3;
} else {
framebuffer.pixelFormat.red_shift = 0;
framebuffer->pixelFormat.red_shift = 0;
if ( framebufferImage->red_mask )
while (!(framebufferImage->red_mask & (1 << framebuffer.pixelFormat.red_shift)))
framebuffer.pixelFormat.red_shift++;
framebuffer.pixelFormat.green_shift = 0;
while (!(framebufferImage->red_mask & (1 << framebuffer->pixelFormat.red_shift)))
framebuffer->pixelFormat.red_shift++;
framebuffer->pixelFormat.green_shift = 0;
if (framebufferImage->green_mask)
while (!(framebufferImage->green_mask & (1 << framebuffer.pixelFormat.green_shift)))
framebuffer.pixelFormat.green_shift++;
framebuffer.pixelFormat.blue_shift = 0;
while (!(framebufferImage->green_mask & (1 << framebuffer->pixelFormat.green_shift)))
framebuffer->pixelFormat.green_shift++;
framebuffer->pixelFormat.blue_shift = 0;
if (framebufferImage->blue_mask)
while (!(framebufferImage->blue_mask & (1 << framebuffer.pixelFormat.blue_shift)))
framebuffer.pixelFormat.blue_shift++;
framebuffer.pixelFormat.red_max = framebufferImage->red_mask >> framebuffer.pixelFormat.red_shift;
framebuffer.pixelFormat.green_max = framebufferImage->green_mask >> framebuffer.pixelFormat.green_shift;
framebuffer.pixelFormat.blue_max = framebufferImage->blue_mask >> framebuffer.pixelFormat.blue_shift;
while (!(framebufferImage->blue_mask & (1 << framebuffer->pixelFormat.blue_shift)))
framebuffer->pixelFormat.blue_shift++;
framebuffer->pixelFormat.red_max = framebufferImage->red_mask >> framebuffer->pixelFormat.red_shift;
framebuffer->pixelFormat.green_max = framebufferImage->green_mask >> framebuffer->pixelFormat.green_shift;
framebuffer->pixelFormat.blue_max = framebufferImage->blue_mask >> framebuffer->pixelFormat.blue_shift;
}
scanner = new XUpdateScanner( dpy, QApplication::desktop()->winId(), &framebuffer );
scanner = new XUpdateScanner( dpy, QApplication::desktop()->winId(), framebuffer );
}
void RFBConnection::destroyFramebuffer()
{
delete scanner;
delete framebuffer;
XDestroyImage(framebufferImage);
}

View File

@@ -50,7 +50,8 @@ using namespace rfb;
class RFBConnection : public QObject, public Server {
Q_OBJECT
public:
RFBConnection(Display *dpy, int fd, const QString &cpassword);
RFBConnection(Display *dpy, int fd,
const QString &cpassword, bool allowInput);
~RFBConnection();
virtual void handleKeyEvent(KeyEvent &keyEvent);
virtual void handlePointerEvent(PointerEvent &pointerEvent);
@@ -65,8 +66,8 @@ private:
int fd;
int buttonMask;
bool allowInput;
Framebuffer framebuffer;
XUpdateScanner *scanner;
Display *dpy;

View File

@@ -33,84 +33,99 @@
RFBController::RFBController(Configuration *c) :
configuration(c),
socket(0),
connection(0),
idleUpdateScheduled(false)
{
start();
startServer();
}
RFBController::~RFBController() {
delete serversocket;
delete connection;
delete socket;
if (socket)
delete socket;
if (connection)
delete connection;
}
void RFBController::start() {
void RFBController::startServer() {
serversocket = new KServerSocket(configuration->port(), false);
connect(serversocket, SIGNAL(accepted()), SLOT(accepted()));
connect(serversocket, SIGNAL(accepted(KSocket*)), SLOT(accepted(KSocket*)));
serversocket->bindAndListen();
// TODO: error message if bindAndListen fails (port in use)
}
void RFBController::rebind() {
if (serversocket) {
delete serversocket;
start();
}
delete serversocket;
startServer();
}
void RFBController::idleSlot() {
idleUpdateScheduled = false;
if (connection) {
connection->sendIncrementalFramebufferUpdate();
checkWritable();
}
}
// called when KServerSocket accepted a connection. Closes KServerSocket.
void RFBController::accepted() {
int sockFd = serversocket->socket();
KSocket *s;
/* called when KServerSocket accepted a connection.
Refuses the connection if there is already a connection.
*/
void RFBController::accepted(KSocket *s) {
int sockFd = s->socket();
if (sockFd < 0)
kdDebug("Negative server socket?");
kdError() << "Got negative socket (error)" << endl;
if (socket) {
kdWarning() << "refuse 2nd connection" << endl;
delete s;
return;
}
int one = 1;
setsockopt(sockFd, IPPROTO_TCP, TCP_NODELAY,
(char *)&one, sizeof(one));
fcntl(sockFd, F_SETFL, O_NONBLOCK);
s = new KSocket(sockFd);
socket = s;
// TODO: ASK USER FOR PERMISSION HERE BEFORE GOING ON
// TODO: also handle case if remote closes while dialog is shown
delete serversocket;
serversocket = 0;
socket = s;
connect(s, SIGNAL(readEvent(KSocket*)), SLOT(sockedReadable()));
connect(s, SIGNAL(writeEvent(KSocket*)), SLOT(sockedWritable()));
connect(s, SIGNAL(closeEvent(KSocket*)), SLOT(sockedClosed()));
connect(s, SIGNAL(readEvent(KSocket*)), SLOT(socketReadable()));
connect(s, SIGNAL(writeEvent(KSocket*)), SLOT(socketWritable()));
connect(s, SIGNAL(closeEvent(KSocket*)), SLOT(closeSession()));
s->enableRead(true);
s->enableWrite(true);
connection = new RFBConnection(qt_xdisplay(), sockFd,
configuration->password());
checkWritable();
configuration->password(),
configuration->allowDesktopControl());
emit sessionEstablished();
}
void RFBController::checkWritable() {
void RFBController::checkWriteBuffer() {
BufferedConnection *bc = connection->bufferedConnection;
socket->enableWrite((bc->senderBuffer.end - bc->senderBuffer.pos) > 0);
}
void RFBController::idleSlot() {
kdDebug() << "Idle 1" << endl;
idleUpdateScheduled = false;
if (connection) {
kdDebug() << "Idle 2" << endl;
connection->scanUpdates();
connection->sendIncrementalFramebufferUpdate();
checkWriteBuffer();
}
}
void RFBController::prepareIdleUpdate() {
if (!idleUpdateScheduled)
kdDebug() << "test schedule, isScheduled? " << idleUpdateScheduled<< endl;
BufferedConnection *bc = connection->bufferedConnection;
if (((bc->senderBuffer.end - bc->senderBuffer.pos) == 0) &&
!idleUpdateScheduled) {
QTimer::singleShot(0, this, SLOT(idleSlot()));
idleUpdateScheduled = true;
idleUpdateScheduled = true;
kdDebug() << "Scheduled!" << endl;
}
}
void RFBController::socketReadable() {
ASSERT(socket);
int fd = socket->socket();
BufferedConnection *bc = connection->bufferedConnection;
prepareIdleUpdate();
int count = read(fd,
bc->receiverBuffer.data,
bc->receiverBuffer.size);
@@ -121,7 +136,7 @@ void RFBController::socketReadable() {
}
while (connection->currentState && bc->hasReceiverBufferData()) {
connection->update();
checkWritable();
checkWriteBuffer();
}
bc->receiverBuffer.pos = 0;
bc->receiverBuffer.end = 0;
@@ -132,31 +147,34 @@ void RFBController::socketReadable() {
void RFBController::socketWritable() {
ASSERT(socket);
kdDebug() << "write slot" << endl;
int fd = socket->socket();
BufferedConnection *bc = connection->bufferedConnection;
ASSERT((bc->senderBuffer.end - bc->senderBuffer.pos) > 0);
// TODO: what to do if fd < 0?
prepareIdleUpdate();
int count = write(fd,
bc->senderBuffer.data + bc->senderBuffer.pos,
bc->senderBuffer.end - bc->senderBuffer.pos);
if (count >= 0)
if (count >= 0) {
bc->senderBuffer.pos += count;
else {
} else {
// TODO: what to do if write failed
}
checkWritable();
kdDebug() << "written " << count << " left " << (bc->senderBuffer.end - bc->senderBuffer.pos) << endl;
prepareIdleUpdate();
checkWriteBuffer();
}
void RFBController::closeSession() {
if (!connection)
if (!socket)
return;
delete connection;
if (connection) {
delete connection;
connection = 0;
emit sessionFinished();
}
delete socket;
connection = 0;
socket = 0;
emit sessionFinished();
start();
}
#include "rfbcontroller.moc"

View File

@@ -34,9 +34,10 @@ using namespace rfb;
/**
* Manages sockets, drives the RGBConnection and triggers the connection
* dialog.
* The controller has two states: 'waiting for connection' and 'connected'.
* In the former serversocket is set and socket and connection are null, in
* the latter serversocket is null and socket and connection are set.
* The controller has three states: 'waiting for connection',
* 'waiting for confirmation' and 'connected'. In the first state socket and
* connection are null, in the second socket is set and in the last both are
* set.
* @author Tim Jansen
*/
class RFBController : public QObject {
@@ -54,8 +55,8 @@ signals:
void sessionFinished();
private:
void start();
void checkWritable();
void startServer();
void checkWriteBuffer();
void prepareIdleUpdate();
Configuration *configuration;
@@ -66,7 +67,7 @@ private:
private slots:
void idleSlot();
void accepted();
void accepted(KSocket*);
void socketReadable();
void socketWritable();
};

View File

@@ -1,5 +1,5 @@
/***************************************************************************
trayicon.cpp - description
trayicon.cpp
-------------------
begin : Tue Dec 11 2001
copyright : (C) 2001 by Tim Jansen
@@ -30,7 +30,11 @@ TrayIcon::TrayIcon() : KSystemTray() {
configureAction = new KAction(i18n("&Configure KRfb"));
configureAction->plug(contextMenu());
closeConnectionAction = new KAction(i18n("Close connection"));
closeConnectionAction->plug(contextMenu());
closeConnectionAction->setEnabled(false);
connect(configureAction, SIGNAL(activated()), SIGNAL(showConfigure()));
connect(closeConnectionAction, SIGNAL(activated()),
SIGNAL(connectionClosed()));
show();
}
@@ -39,10 +43,10 @@ TrayIcon::~TrayIcon(){
void TrayIcon::openConnection(){
setPixmap(trayIconOpen);
closeConnectionAction->plug(contextMenu());
closeConnectionAction->setEnabled(true);
}
void TrayIcon::closeConnection(){
setPixmap(trayIconClosed);
closeConnectionAction->unplug(contextMenu());
closeConnectionAction->setEnabled(false);
}

View File

@@ -33,13 +33,16 @@ public:
TrayIcon();
~TrayIcon();
public slots:
void closeConnection();
void openConnection();
private:
KPixmap trayIconOpen;
KPixmap trayIconClosed;
KAction* closeConnectionAction;
KAction* configureAction;
signals:
void connectionClosed();
void showConfigure();