author | treke <treke> | 2002-12-22 00:58:46 (UTC) |
---|---|---|
committer | treke <treke> | 2002-12-22 00:58:46 (UTC) |
commit | 17d7f11b16b650f6ee2b5c440506167ea41fbfe5 (patch) (side-by-side diff) | |
tree | cd5924c9e374a82c1cac6433dce098f3f45f4286 | |
parent | 6853d02989fc01e5a65048aca9749c20e0f5d095 (diff) | |
download | opie-17d7f11b16b650f6ee2b5c440506167ea41fbfe5.zip opie-17d7f11b16b650f6ee2b5c440506167ea41fbfe5.tar.gz opie-17d7f11b16b650f6ee2b5c440506167ea41fbfe5.tar.bz2 |
1) Fixed a bug where double clicking a blank spot on the bookmark list
caused a segfault.
2) Removed support for copying from the server. Trying to setText in the
clipboard would segfault everytime from within the KRFBDecoder. Doesnt
seem to like being called from within a slot.
-rw-r--r-- | noncore/comm/keypebble/krfbcanvas.cpp | 4 | ||||
-rw-r--r-- | noncore/comm/keypebble/krfbdecoder.cpp | 5 | ||||
-rw-r--r-- | noncore/comm/keypebble/kvnc.cpp | 1 |
3 files changed, 5 insertions, 5 deletions
diff --git a/noncore/comm/keypebble/krfbcanvas.cpp b/noncore/comm/keypebble/krfbcanvas.cpp index 049bbd4..bc71c90 100644 --- a/noncore/comm/keypebble/krfbcanvas.cpp +++ b/noncore/comm/keypebble/krfbcanvas.cpp @@ -1,213 +1,209 @@ #include "krfbconnection.h" #include "krfbcanvas.h" #include "krfbserver.h" #include "krfbbuffer.h" #include <qpe/config.h> #include <qpe/qpeapplication.h> #include <qapplication.h> #include <qclipboard.h> #include <qaction.h> #include <qpixmap.h> #include <qpoint.h> #include <qapplication.h> #include <qmainwindow.h> #include <qiconset.h> KRFBCanvas::KRFBCanvas( QWidget *parent, const char *name ) : QScrollView( parent, name ) { connection_ = new KRFBConnection(); connect( connection_, SIGNAL( loggedIn() ), this, SLOT( loggedIn() ) ); loggedIn_ = false; //QPEApplication::setStylusOperation(viewport(), QPEApplication::RightOnHold); viewport()->setFocusPolicy( QWidget::StrongFocus ); viewport()->setFocus(); nextRightClick=0; nextDoubleClick=0; } KRFBCanvas::~KRFBCanvas() { } void KRFBCanvas::openConnection(KRFBServer server) { QCString host = server.hostname.latin1(); password=server.password; connection_->connectTo( server); } void KRFBCanvas::openURL( const QUrl &url ) { if ( loggedIn_ ) { qWarning( "openURL invoked when logged in\n" ); return; } QCString host = url.host().latin1(); int display = url.port(); // connection_->connectTo( host, display ); } void KRFBCanvas::closeConnection() { loggedIn_ = false; connection_->disconnect(); viewport()->setMouseTracking( false ); viewport()->setBackgroundMode( PaletteDark ); setBackgroundMode( PaletteDark ); update(); } void KRFBCanvas::bell() { if ( connection_->options()->deIconify ) { topLevelWidget()->raise(); topLevelWidget()->show(); } } void KRFBCanvas::loggedIn() { qWarning( "Ok, we're logged in" ); // // Get ready for action // loggedIn_ = true; viewport()->setMouseTracking( true ); viewport()->setBackgroundMode( NoBackground ); setBackgroundMode( NoBackground ); // Start using the buffer connect( connection_->buffer(), SIGNAL( sizeChanged( int, int ) ), this, SLOT( resizeContents(int,int) ) ); connect( connection_->buffer(), SIGNAL( updated( int, int, int, int ) ), this, SLOT( viewportUpdate(int,int,int,int) ) ); connect( connection_->buffer(), SIGNAL( bell() ), this, SLOT( bell() ) ); connect( qApp->clipboard(), SIGNAL( dataChanged() ), this, SLOT( clipboardChanged() ) ); } void KRFBCanvas::viewportPaintEvent( QPaintEvent *e ) { QRect r = e->rect(); if ( loggedIn_ ) { QPixmap p; bitBlt( viewport(), r.x(), r.y(), connection_->buffer()->pixmap(), r.x() + contentsX(), r.y() + contentsY(), r.width(), r.height() ); } else { QScrollView::viewportPaintEvent( e ); } } void KRFBCanvas::viewportUpdate( int x, int y, int w, int h ) { updateContents( x, y, w, h ); } void KRFBCanvas::contentsMousePressEvent( QMouseEvent *e ) { if (nextDoubleClick) { connection_->buffer()->mouseEvent( &QMouseEvent(QEvent::MouseButtonPress, e->pos(),LeftButton,LeftButton)); connection_->buffer()->mouseEvent( &QMouseEvent(QEvent::MouseButtonRelease, e->pos(),LeftButton,0)); connection_->buffer()->mouseEvent( &QMouseEvent(QEvent::MouseButtonRelease, e->pos(),LeftButton,0)); connection_->buffer()->mouseEvent( &QMouseEvent(QEvent::MouseButtonPress, e->pos(),NoButton,NoButton)); connection_->buffer()->mouseEvent( &QMouseEvent(QEvent::MouseButtonRelease, e->pos(),NoButton,0)); } if (nextRightClick) { connection_->buffer()->mouseEvent( &QMouseEvent(QEvent::MouseButtonPress, e->pos(),RightButton,RightButton)); connection_->buffer()->mouseEvent( &QMouseEvent(QEvent::MouseButtonRelease, e->pos(),RightButton,0)); connection_->buffer()->mouseEvent( &QMouseEvent(QEvent::MouseButtonPress, e->pos(),NoButton,NoButton)); connection_->buffer()->mouseEvent( &QMouseEvent(QEvent::MouseButtonRelease, e->pos(),NoButton,0)); } else if ( loggedIn_ ) connection_->buffer()->mouseEvent( e ); - qDebug("Press"); - qDebug(QString::number(e->type()==QEvent::MouseButtonPress)); } void KRFBCanvas::contentsMouseReleaseEvent( QMouseEvent *e ) { if ( loggedIn_ && !nextRightClick && !nextDoubleClick) { connection_->buffer()->mouseEvent( e ); } nextRightClick=0; nextDoubleClick=0; - qDebug("Release"); - qDebug(QString::number(e->button())); } void KRFBCanvas::contentsMouseMoveEvent( QMouseEvent *e ) { if ( loggedIn_ ) connection_->buffer()->mouseEvent( e ); } void KRFBCanvas::keyPressEvent( QKeyEvent *e ) { if ( loggedIn_ ) connection_->buffer()->keyPressEvent( e ); } void KRFBCanvas::keyReleaseEvent( QKeyEvent *e ) { if ( loggedIn_ ) connection_->buffer()->keyReleaseEvent( e ); } void KRFBCanvas::refresh() { if ( loggedIn_ ) connection_->refresh(); } void KRFBCanvas::clipboardChanged() { if ( loggedIn_ ) { connection_->sendCutText( qApp->clipboard()->text() ); } } void KRFBCanvas::sendCtlAltDel( void) { if ( loggedIn_ ) { connection_->buffer()->keyPressEvent( &QKeyEvent(QEvent::KeyPress,Qt::Key_Control, 0,0)); connection_->buffer()->keyPressEvent( &QKeyEvent(QEvent::KeyPress,Qt::Key_Alt, 0,0)); connection_->buffer()->keyPressEvent( &QKeyEvent(QEvent::KeyPress,Qt::Key_Delete, 0,0)); connection_->buffer()->keyPressEvent( &QKeyEvent(QEvent::KeyRelease,Qt::Key_Control, 0,0)); connection_->buffer()->keyPressEvent( &QKeyEvent(QEvent::KeyRelease,Qt::Key_Alt, 0,0)); connection_->buffer()->keyPressEvent( &QKeyEvent(QEvent::KeyRelease,Qt::Key_Delete, 0,0)); } } void KRFBCanvas::markDoubleClick( void) { nextRightClick=1; } void KRFBCanvas::markRightClick( void) { nextRightClick=1; } diff --git a/noncore/comm/keypebble/krfbdecoder.cpp b/noncore/comm/keypebble/krfbdecoder.cpp index 94e3b79..33418ae 100644 --- a/noncore/comm/keypebble/krfbdecoder.cpp +++ b/noncore/comm/keypebble/krfbdecoder.cpp @@ -1,841 +1,844 @@ #include "krfbconnection.h" #include "krfbserver.h" #include "krfbserverinfo.h" #include "krfbdecoder.h" #include "krfbbuffer.h" #include <qpe/qpeapplication.h> #include <qpixmap.h> #include <qsocket.h> #include <qevent.h> #include <qstring.h> #include <qclipboard.h> #include <assert.h> // // Endian stuff // #ifndef KDE_USE_FINAL const int endianTest = 1; #endif #define Swap16IfLE(s) \ (*(char *)&endianTest ? ((((s) & 0xff) << 8) | (((s) >> 8) & 0xff)) : (s)) #define Swap32IfLE(l) \ (*(char *)&endianTest ? ((((l) & 0xff000000) >> 24) | \ (((l) & 0x00ff0000) >> 8) | \ (((l) & 0x0000ff00) << 8) | \ (((l) & 0x000000ff) << 24)) : (l)) // // The lengths of the messages we need to wait for // const int ServerInitLength = 24; const int UpdateHeaderLength = 4; const int RectHeaderLength = 12; const int RectChunkSize = 4; const int CopyRectPosLength = 4; const int ServerCutLenLength = 7; // // Client -> Server Message Identifiers // static CARD8 SetPixelFormatId = 0; //static CARD8 FixColourMapEntriesId = 1; // Not used static CARD8 SetEncodingsId = 2; static CARD8 UpdateRequestId = 3; static CARD8 KeyEventId = 4; static CARD8 PointerEventId = 5; static CARD8 ClientCutTextId = 6; // // Server -> Client Message Identifiers // static CARD8 UpdateId = 0; static CARD8 BellId = 2; static CARD8 ServerCutId = 3; // // Encoding identifiers // static CARD32 RawEncoding = Swap32IfLE( 0 ); static CARD32 CopyRectEncoding = Swap32IfLE(1 ); static CARD32 RreEncoding = Swap32IfLE( 2 ); static CARD32 CorreEncoding = Swap32IfLE( 4 ); static CARD32 HexTileEncoding = Swap32IfLE( 5 ); static struct { int keysym; int keycode; } keyMap[] = { { 0xff08, Qt::Key_Backspace }, { 0xff09, Qt::Key_Tab }, { 0xff0d, Qt::Key_Return }, { 0xff1b, Qt::Key_Escape }, { 0xff63, Qt::Key_Insert }, { 0xffff, Qt::Key_Delete }, { 0xff50, Qt::Key_Home }, { 0xff57, Qt::Key_End }, { 0xff55, Qt::Key_Prior }, { 0xff56, Qt::Key_Next }, { 0xff51, Qt::Key_Left }, { 0xff52, Qt::Key_Up }, { 0xff53, Qt::Key_Right }, { 0xff54, Qt::Key_Down }, { 0xffbe, Qt::Key_F1 }, { 0xffbf, Qt::Key_F2 }, { 0xffc0, Qt::Key_F3 }, { 0xffc1, Qt::Key_F4 }, { 0xffc2, Qt::Key_F5 }, { 0xffc3, Qt::Key_F6 }, { 0xffc4, Qt::Key_F7 }, { 0xffc5, Qt::Key_F8 }, { 0xffc6, Qt::Key_F9 }, { 0xffc7, Qt::Key_F10 }, { 0xffc8, Qt::Key_F11 }, { 0xffc9, Qt::Key_F12 }, { 0xffe1, Qt::Key_Shift }, { 0xffe2, Qt::Key_Shift }, { 0xffe3, Qt::Key_Control }, { 0xffe4, Qt::Key_Control }, { 0xffe7, Qt::Key_Meta }, { 0xffe8, Qt::Key_Meta }, { 0xffe9, Qt::Key_Alt }, { 0xffea, Qt::Key_Alt }, { 0, 0 } }; KRFBDecoder::KRFBDecoder( KRFBConnection *con ) : QObject( con, "RFB Decoder" ) { assert( con ); assert( con->state() == KRFBConnection::Connected ); this->con = con; this->buf = 0; this->info = 0; this->format = 0; this->buttonMask = 0; currentState = Idle; } KRFBDecoder::~KRFBDecoder() { if ( info ) delete info; if ( format ) delete format; } void KRFBDecoder::start() { sendClientInit(); } void KRFBDecoder::sendClientInit() { con->write( &( con->options()->shared ), 1 ); // Wait for server init qWarning( "Waiting for server init" ); static QString statusMsg = tr( "Waiting for server initialisation..." ); emit status( statusMsg ); currentState = AwaitingServerInit; connect( con, SIGNAL( gotEnoughData() ), SLOT( gotServerInit() ) ); con->waitForData( ServerInitLength ); } void KRFBDecoder::gotServerInit() { qWarning( "Got server init" ); disconnect( con, SIGNAL( gotEnoughData() ), this, SLOT( gotServerInit() ) ); if ( info ) delete info; info = new KRFBServerInfo; CHECK_PTR( info ); con->read( &(info->width), 2 ); info->width = Swap16IfLE( info->width ); con->read( &info->height, 2 ); info->height = Swap16IfLE( info->height ); con->read( &(info->bpp), 1 ); con->read( &(info->depth), 1 ); con->read( &(info->bigEndian), 1 ); con->read( &(info->trueColor), 1 ); con->read( &(info->redMax), 2 ); info->redMax = Swap16IfLE( info->redMax ); con->read( &(info->greenMax), 2 ); info->greenMax = Swap16IfLE( info->greenMax ); con->read( &(info->blueMax), 2 ); info->blueMax = Swap16IfLE( info->blueMax ); con->read( &(info->redShift), 1 ); con->read( &(info->greenShift), 1 ); con->read( &(info->blueShift), 1 ); con->read( info->padding, 3 ); con->read( &(info->nameLength), 4 ); info->nameLength = Swap32IfLE( info->nameLength ); qWarning( "Width = %d, Height = %d", info->width, info->height ); qWarning( "Bpp = %d, Depth = %d, Big = %d, True = %d", info->bpp, info->depth, info->bigEndian, info->trueColor ); qWarning( "RedMax = %d, GreenMax = %d, BlueMax = %d", info->redMax, info->greenMax, info->blueMax ); qWarning( "RedShift = %d, GreenShift = %d, BlueShift = %d", info->redShift, info->greenShift,info-> blueShift ); buf->resize( info->width/con->options()->scaleFactor, info->height /con->options()->scaleFactor); // Wait for desktop name qWarning( "Waiting for desktop name" ); static QString statusMsg = tr( "Waiting for desktop name..." ); emit status( statusMsg ); currentState = AwaitingDesktopName; connect( con, SIGNAL( gotEnoughData() ), SLOT( gotDesktopName() ) ); con->waitForData( info->nameLength ); } void KRFBDecoder::gotDesktopName() { assert( info ); assert( currentState == AwaitingDesktopName ); qWarning( "Got desktop name" ); disconnect( con, SIGNAL( gotEnoughData() ), this, SLOT( gotDesktopName() ) ); char *buf = new char[ info->nameLength + 1 ]; CHECK_PTR( buf ); con->read( buf, info->nameLength ); buf[ info->nameLength ] = '\0'; info->name = buf; qWarning( "Desktop: %s", info->name.latin1() ); delete buf; // Get the format we'll really use and tell the server decidePixelFormat(); sendPixelFormat(); sendAllowedEncodings(); currentState = Idle; QString msg; msg = tr( "Connected to %1" ); msg = msg.arg( info->name ); emit status( msg ); sendUpdateRequest( false ); } void KRFBDecoder::decidePixelFormat() { assert( info ); if ( format ) delete format; format = new KRFBPixelFormat; CHECK_PTR( format ); // What depth do we want? // // We'll use the minimum of the remote and local depths, UNLESS an // eight bit session has been specifically requested by the user. int screenDepth = QPixmap::defaultDepth(); int bestDepth = ( screenDepth > info->depth ) ? info->depth : screenDepth; int chosenDepth; if ( con->options()->colors256 ) chosenDepth = 8; else chosenDepth = bestDepth; qWarning( "Screen depth=%d, server depth=%d, best depth=%d, " \ "eight bit %d, chosenDepth=%d", screenDepth, info->depth, bestDepth, con->options()->colors256, chosenDepth ); format->depth = chosenDepth; // If we're using the servers native depth if ( chosenDepth == info->depth ) { // Use the servers native format format->bpp = info->bpp; // format->bigEndian = info->bigEndian; format->bigEndian = true; format->trueColor = info->trueColor; format->redMax = info->redMax; format->greenMax = info->greenMax; format->blueMax = info->blueMax; format->redShift = info->redShift; format->greenShift = info->greenShift; format->blueShift = info->blueShift; } else { if ( chosenDepth == 8 ) { format->bpp = 8; format->bigEndian = true; format->trueColor = true; format->redMax = 7; format->greenMax = 7; format->blueMax = 3; format->redShift = 0; format->greenShift = 3; format->blueShift = 6; } } format->redMax = Swap16IfLE( format->redMax ); format->greenMax = Swap16IfLE( format->greenMax ); format->blueMax = Swap16IfLE( format->blueMax ); } void KRFBDecoder::sendPixelFormat() { static char padding[3]; con->write( &SetPixelFormatId, 1 ); con->write( padding, 3 ); con->write( &(format->bpp), 1 ); con->write( &(format->depth), 1 ); con->write( &(format->bigEndian), 1 ); con->write( &(format->trueColor), 1 ); con->write( &(format->redMax), 2 ); con->write( &(format->greenMax), 2 ); con->write( &(format->blueMax), 2 ); con->write( &(format->redShift), 1 ); con->write( &(format->greenShift), 1 ); con->write( &(format->blueShift), 1 ); con->write( format->padding, 3 ); // Padding } void KRFBDecoder::sendAllowedEncodings() { static CARD8 padding[1]; con->write( &SetEncodingsId, 1 ); con->write( padding, 1 ); static CARD16 noEncodings = con->options()->encodings(); noEncodings = Swap16IfLE( noEncodings ); con->write( &noEncodings, 2 ); if ( con->options()->corre ) con->write( &CorreEncoding, 4 ); if ( con->options()->hexTile ) con->write( &HexTileEncoding, 4 ); if ( con->options()->rre ) con->write( &RreEncoding, 4 ); if ( con->options()->copyrect ) con->write( &CopyRectEncoding, 4 ); // We always support this con->write( &RawEncoding, 4 ); } void KRFBDecoder::sendUpdateRequest( bool incremental ) { if ( currentState != Idle ) return; con->write( &UpdateRequestId, 1 ); con->write( &incremental, 1 ); static CARD16 x = 0, y = 0; static CARD16 w = Swap16IfLE( info->width ); static CARD16 h = Swap16IfLE( info->height ); con->write( &x, 2 ); con->write( &y, 2 ); con->write( &w, 2 ); con->write( &h, 2 ); // Now wait for the update currentState = AwaitingUpdate; connect( con, SIGNAL( gotEnoughData() ), SLOT( gotUpdateHeader() ) ); con->waitForData( UpdateHeaderLength ); } void KRFBDecoder::gotUpdateHeader() { assert( currentState == AwaitingUpdate ); // qWarning( "Got update header" ); disconnect( con, SIGNAL( gotEnoughData() ), this, SLOT( gotUpdateHeader() ) ); CARD8 msgType; con->read( &msgType, 1 ); if ( msgType != UpdateId ) { // We might have a bell or server cut if ( msgType == ServerCutId ) { oldState = currentState; gotServerCut(); } else if ( msgType == BellId ) { oldState = currentState; gotBell(); } else { int msg = msgType; QString protocolError = tr( "Protocol Error: Message Id %1 was " "found when expecting an update " "message." ).arg( msg ); currentState = Error; emit error( protocolError ); } return; } CARD8 padding; con->read( &padding, 1 ); con->read( &noRects, 2 ); noRects = Swap16IfLE( noRects ); // qWarning( "Expecting %d rects", noRects ); // Now wait for the data currentState = AwaitingRectHeader; connect( con, SIGNAL( gotEnoughData() ), SLOT( gotRectHeader() ) ); con->waitForData( RectHeaderLength ); } void KRFBDecoder::gotRectHeader() { assert( currentState == AwaitingRectHeader ); // qWarning( "Got rect header" ); disconnect( con, SIGNAL( gotEnoughData() ), this, SLOT( gotRectHeader() ) ); con->read( &x, 2 ); x = Swap16IfLE( x ); con->read( &y, 2 ); y = Swap16IfLE( y ); con->read( &w, 2 ); w = Swap16IfLE( w ); con->read( &h, 2 ); h = Swap16IfLE( h ); con->read( &encoding, 4 ); // CARD32 encodingLocal = Swap32IfLE( encoding ); // qWarning( "Rect: x=%d, y= %d, w=%d, h=%d, encoding=%ld", // x, y, w, h, encodingLocal ); // // Each encoding needs to be handled differently. Some require // waiting for more data, but others like a copyrect do not. // Our constants have already been byte swapped, so we use // the remote value as is. // if ( encoding == RawEncoding ) { // qWarning( "Raw encoding" ); handleRawRect(); } else if ( encoding == CopyRectEncoding ) { // qWarning( "CopyRect encoding" ); handleCopyRect(); } else if ( encoding == RreEncoding ) { qWarning( "RRE encoding" ); handleRRERect(); } else if ( encoding == CorreEncoding ) { qWarning( "CoRRE encoding" ); handleCoRRERect(); } else if ( encoding == HexTileEncoding ) { qWarning( "HexTile encoding" ); handleHexTileRect(); } else { int msg = Swap32IfLE( encoding ); QString protocolError = tr( "Protocol Error: An unknown encoding was " "used by the server %1" ).arg( msg ); currentState = Error; qWarning( "Unknown encoding, %d", msg ); emit error( protocolError ); return; } } // // Raw Encoding // void KRFBDecoder::handleRawRect() { // We need something a bit cleverer here to handle large // rectanges nicely. The chunking should be based on the // overall size (but has to be in complete lines). // qWarning( "Handling a raw rect chunk" ); // CARD32 lineCount = w * format->bpp / 8; if ( h > RectChunkSize ) { // if ( con->sock->size() / lineCount ) { // getRawRectChunk( con->sock->size() / lineCount ); // } // else { getRawRectChunk( RectChunkSize ); // } } else { getRawRectChunk( h ); } } void KRFBDecoder::getRawRectChunk( int lines ) { this->lines = lines; CARD32 count = lines * w * format->bpp / 8; // Wait for server init // qWarning( "Waiting for raw rect chunk, %ld", count ); currentState = AwaitingRawRectChunk; connect( con, SIGNAL( gotEnoughData() ), SLOT( gotRawRectChunk() ) ); con->waitForData( count ); } void KRFBDecoder::gotRawRectChunk() { assert( currentState == AwaitingRawRectChunk ); disconnect( con, SIGNAL( gotEnoughData() ), this, SLOT( gotRawRectChunk() ) ); // qWarning( "Got raw rect chunk" ); // // Read the rect data and copy it to the buffer. // // TODO: Replace this! int count = lines * w * format->bpp / 8; char *hack = new char[ count ]; con->read( hack, count ); buf->drawRawRectChunk( hack, x, y, w, lines ); delete hack; // /TODO: h = h - lines; y = y + lines; if ( h > 0 ) { handleRawRect(); } else { noRects--; // qWarning( "There are %d rects left", noRects ); if ( noRects ) { currentState = AwaitingRectHeader; connect( con, SIGNAL( gotEnoughData() ), SLOT( gotRectHeader() ) ); con->waitForData( RectHeaderLength ); } else currentState = Idle; } } // // Copy Rectangle Encoding // void KRFBDecoder::handleCopyRect() { currentState = AwaitingCopyRectPos; connect( con, SIGNAL( gotEnoughData() ), SLOT( gotCopyRectPos() ) ); con->waitForData( CopyRectPosLength ); } void KRFBDecoder::gotCopyRectPos() { disconnect( con, SIGNAL( gotEnoughData() ), this, SLOT( gotCopyRectPos() ) ); CARD16 srcX; CARD16 srcY; con->read( &srcX, 2 ); con->read( &srcY, 2 ); srcX = Swap16IfLE( srcX ); srcY = Swap16IfLE( srcY ); buf->copyRect( srcX, srcY, x, y, w, h ); noRects--; // qWarning( "There are %d rects left", noRects ); if ( noRects ) { currentState = AwaitingRectHeader; connect( con, SIGNAL( gotEnoughData() ), SLOT( gotRectHeader() ) ); con->waitForData( RectHeaderLength ); } else currentState = Idle; } void KRFBDecoder::handleRRERect() { qWarning( "RRE not implemented" ); } void KRFBDecoder::handleCoRRERect() { qWarning( "CoRRE not implemented" ); } void KRFBDecoder::handleHexTileRect() { qWarning( "HexTile not implemented" ); } void KRFBDecoder::sendMouseEvent( QMouseEvent *e ) { // Deal with the buttons if ( e->type() != QEvent::MouseMove ) { buttonMask = 0; if ( e->type() == QEvent::MouseButtonPress ) { if ( e->button() & LeftButton ) buttonMask |= 0x01; if ( e->button() & MidButton ) buttonMask |= 0x04; if ( e->button() & RightButton ) buttonMask |= 0x02; } else if ( e->type() == QEvent::MouseButtonRelease ) { if ( e->button() & LeftButton ) buttonMask &= 0x06; if ( e->button() & MidButton ) buttonMask |= 0x03; if ( e->button() & RightButton ) buttonMask |= 0x05; } } // HACK: Scaling CARD16 x = Swap16IfLE( e->x() * con->options()->scaleFactor ); CARD16 y = Swap16IfLE( e->y() * con->options()->scaleFactor ); con->write( &PointerEventId, 1 ); con->write( &buttonMask, 1 ); con->write( &x, 2 ); con->write( &y, 2 ); } void KRFBDecoder::sendCutEvent( const QString &unicode ) { // // Warning: There is a bug in the RFB protocol because there is no way to find // out the codepage in use on the remote machine. This could be fixed by requiring // the remote server to use utf8 etc. but for now we have to assume they're the // same. I've reported this problem to the ORL guys, but they apparantly have no // immediate plans to fix the issue. :-( (rich) // CARD8 padding[3]; QCString text = unicode.local8Bit(); CARD32 length = text.length(); length = Swap32IfLE( length ); con->write( &ClientCutTextId, 1 ); con->write( &padding, 3 ); con->write( &length, 4 ); con->write( text.data(), length ); } void KRFBDecoder::gotServerCut() { qWarning( "Got server cut" ); currentState = AwaitingServerCutLength; connect( con, SIGNAL( gotEnoughData() ), SLOT( gotServerCutLength() ) ); con->waitForData( ServerCutLenLength ); } void KRFBDecoder::gotServerCutLength() { assert( currentState = AwaitingServerCutLength ); disconnect( con, SIGNAL( gotEnoughData() ), this, SLOT( gotServerCutLength() ) ); CARD8 padding[3]; con->read( padding, 3 ); con->read( &serverCutTextLen, 4 ); serverCutTextLen = Swap32IfLE( serverCutTextLen ); currentState = AwaitingServerCutText; connect( con, SIGNAL( gotEnoughData() ), SLOT( gotServerCutText() ) ); con->waitForData( serverCutTextLen ); } void KRFBDecoder::gotServerCutText() { assert( currentState = AwaitingServerCutText ); disconnect( con, SIGNAL( gotEnoughData() ), this, SLOT( gotServerCutText() ) ); + // // Warning: There is a bug in the RFB protocol because there is no way to find // out the codepage in use on the remote machine. This could be fixed by requiring // the remote server to use utf8 etc. but for now we have to assume they're the // same. I've reported this problem to the ORL guys, but they apparantly have no // immediate plans to fix the issue. :-( (rich) // char *cutbuf = new char[ serverCutTextLen + 1 ]; CHECK_PTR( cutbuf ); con->read( cutbuf, serverCutTextLen ); cutbuf[ serverCutTextLen ] = '\0'; + /* For some reason QApplication::clipboard()->setText() segfaults when called + * from within keypebble's mass of signals and slots qWarning( "Server cut: %s", cutbuf ); QString cutText( cutbuf ); // DANGER!! qApp->clipboard()->setText( cutText ); + */ delete cutbuf; - // Now wait for the update (again) if ( oldState == AwaitingUpdate ) { currentState = AwaitingUpdate; connect( con, SIGNAL( gotEnoughData() ), SLOT( gotUpdateHeader() ) ); con->waitForData( UpdateHeaderLength ); } else if ( oldState == Idle ) { currentState = Idle; } else { qWarning( "Async handled in weird state" ); currentState = oldState; }; } void KRFBDecoder::gotBell() { qWarning( "Got server bell" ); buf->soundBell(); // Now wait for the update (again) if ( oldState == AwaitingUpdate ) { currentState = AwaitingUpdate; connect( con, SIGNAL( gotEnoughData() ), SLOT( gotUpdateHeader() ) ); con->waitForData( UpdateHeaderLength ); } else if ( oldState == Idle ) { currentState = Idle; } else { qWarning( "Async handled in weird state" ); currentState = oldState; }; } void KRFBDecoder::sendKeyPressEvent( QKeyEvent *event ) { int key; key = toKeySym( event ); if ( key ) { key = Swap32IfLE( key ); CARD8 mask = true; CARD16 padding = 0; con->write( &KeyEventId, 1 ); con->write( &mask, 1 ); con->write( &padding, 2 ); con->write( &key, 4 ); } } void KRFBDecoder::sendKeyReleaseEvent( QKeyEvent *event ) { int key; key = toKeySym( event ); if ( key ) { key = Swap32IfLE( key ); CARD8 mask = false; CARD16 padding = 0; con->write( &KeyEventId, 1 ); con->write( &mask, 1 ); con->write( &padding, 2 ); con->write( &key, 4 ); } } int KRFBDecoder::toKeySym( QKeyEvent *k ) { int ke = 0; ke = k->ascii(); // Markus: Crappy hack. I dont know why lower case letters are // not defined in qkeydefs.h. The key() for e.g. 'l' == 'L'. // This sucks. :-( if ( (ke == 'a') || (ke == 'b') || (ke == 'c') || (ke == 'd') || (ke == 'e') || (ke == 'f') || (ke == 'g') || (ke == 'h') || (ke == 'i') || (ke == 'j') || (ke == 'k') || (ke == 'l') || (ke == 'm') || (ke == 'n') || (ke == 'o') || (ke == 'p') || (ke == 'q') || (ke == 'r') || (ke == 's') || (ke == 't') || (ke == 'u') || (ke == 'v') ||( ke == 'w') || (ke == 'x') || (ke == 'y') || (ke == 'z') ) { ke = k->key(); ke = ke + 0x20; return ke; } // qkeydefs = xkeydefs! :-) if ( ( k->key() >= 0x0a0 ) && k->key() <= 0x0ff ) return k->key(); if ( ( k->key() >= 0x20 ) && ( k->key() <= 0x7e ) ) return k->key(); // qkeydefs != xkeydefs! :-( // This is gonna suck :-( int i = 0; while ( keyMap[i].keycode ) { if ( k->key() == keyMap[i].keycode ) return keyMap[i].keysym; i++; } return 0; } diff --git a/noncore/comm/keypebble/kvnc.cpp b/noncore/comm/keypebble/kvnc.cpp index 5b1dc9f..48a442c 100644 --- a/noncore/comm/keypebble/kvnc.cpp +++ b/noncore/comm/keypebble/kvnc.cpp @@ -1,294 +1,295 @@ #include <qiconset.h> #include <qdialog.h> #include <qpixmap.h> #include <qdom.h> #include <qaction.h> #include <qpe/qpemenubar.h> #include <qstatusbar.h> #include <qpopupmenu.h> #include <qpushbutton.h> #include <qpe/qpetoolbar.h> #include <qtimer.h> #include <qmessagebox.h> #include <qspinbox.h> #include <qlistbox.h> #include <qlineedit.h> #include <qpe/qpeapplication.h> #include <qpe/global.h> #include <qpe/qpetoolbar.h> #include <qpe/resource.h> #include <assert.h> #include "kvnc.h" #include "krfbcanvas.h" #include "krfbconnection.h" #include "kvncconndlg.h" #include "krfbserver.h" static int u_id = 1; static int get_unique_id() { return u_id++; } /* XPM */ static char * menu_xpm[] = { "12 12 5 1", " c None", ". c #000000", "+ c #FFFDAD", "@ c #FFFF00", "# c #E5E100", " ", " ", " ......... ", " .+++++++. ", " .+@@@@#. ", " .+@@@#. ", " .+@@#. ", " .+@#. ", " .+#. ", " .+. ", " .. ", " "}; const int StatusTextId = 0; KVNC::KVNC( const char *name ) : QMainWindow( 0, name ,WStyle_ContextHelp) { setCaption( tr("VNC Viewer") ); fullscreen = false; stack = new QWidgetStack( this ); setCentralWidget( stack ); bookmarkSelector=new KVNCBookmarkDlg(); stack->addWidget(bookmarkSelector,get_unique_id()); stack->raiseWidget( bookmarkSelector ); canvas = new KRFBCanvas( stack, "canvas" ); stack->addWidget(canvas,get_unique_id()); setCentralWidget( stack ); connect( bookmarkSelector->bookmarkList, SIGNAL(clicked(QListBoxItem *)), this, SLOT(openConnection(QListBoxItem *)) ); connect( canvas->connection(), SIGNAL(statusChanged(const QString &)), this, SLOT(statusMessage(const QString &)) ); connect( canvas->connection(), SIGNAL(error(const QString &)), this, SLOT(error(const QString &)) ); connect( canvas->connection(), SIGNAL(connected()), this, SLOT(connected()) ); connect( canvas->connection(), SIGNAL(loggedIn()), this, SLOT(loggedIn()) ); connect( canvas->connection(), SIGNAL(disconnected()), this, SLOT(disconnected()) ); setupActions(); cornerButton = new QPushButton( this ); cornerButton->setPixmap( QPixmap( (const char**)menu_xpm ) ); connect( cornerButton, SIGNAL(pressed()), this, SLOT(showMenu()) ); canvas->setCornerWidget( cornerButton ); stack->raiseWidget( bookmarkSelector ); bar= new QToolBar( this ); setToolBarsMovable( false ); setRightJustification(false); QAction *n = new QAction( tr( "New Connection" ), Resource::loadPixmap( "new" ), QString::null, 0, this, 0 ); connect( n, SIGNAL( activated() ), this, SLOT( newConnection() ) ); n->addTo( bar ); QAction *o = new QAction( tr( "Open Bookmark" ), Resource::loadPixmap( "fileopen" ), QString::null, 0, this, 0 ); connect( o, SIGNAL( activated() ), this, SLOT( openConnection() ) ); o->addTo( bar ); QAction *d = new QAction( tr( "Delete Bookmark" ), Resource::loadPixmap( "trash" ), QString::null, 0, this, 0 ); connect( d, SIGNAL( activated() ), this, SLOT( deleteBookmark() ) ); d->addTo( bar ); } KVNC::~KVNC() { } void KVNC::newConnection() { curServer=new KRFBServer; KVNCConnDlg dlg( curServer,this); dlg.showMaximized(); if ( dlg.exec()) { if (!curServer->name.isEmpty()) bookmarkSelector->addBookmark(curServer); canvas->openConnection(*curServer); } else curServer=0; } void KVNC::openConnection( QString name) { curServer=bookmarkSelector->getServer(name); if (curServer) { KVNCConnDlg dlg( curServer,this); dlg.showMaximized(); if ( dlg.exec() ) { canvas->openConnection(*curServer); bookmarkSelector->writeBookmarks(); } else curServer=0; } } void KVNC::openConnection( void ) { openConnection( bookmarkSelector->selectedBookmark()); } void KVNC::openConnection( QListBoxItem * item) { + if (item) openConnection(item->text()); } void KVNC::setupActions() { cornerMenu = new QPopupMenu( this ); fullScreenAction = new QAction( tr("Full Screen"), QString::null, 0, 0 ); connect( fullScreenAction, SIGNAL(activated()), this, SLOT( toggleFullScreen() ) ); fullScreenAction->addTo( cornerMenu ); fullScreenAction->setEnabled( false ); ctlAltDelAction = new QAction( tr("Send Contrl-Alt-Delete"), QString::null, 0, 0 ); connect( ctlAltDelAction, SIGNAL(activated()), canvas, SLOT( sendCtlAltDel() ) ); ctlAltDelAction->addTo( cornerMenu ); ctlAltDelAction->setEnabled( false ); disconnectAction = new QAction( tr("Disconnect"), QString::null, 0, 0 ); connect( disconnectAction, SIGNAL(activated()), this, SLOT( closeConnection() ) ); disconnectAction->addTo( cornerMenu ); disconnectAction->setEnabled( false ); doubleClickAction = new QAction( tr("Next Click is Double Click"), QString::null, 0, 0 ); connect( doubleClickAction, SIGNAL(activated()), canvas, SLOT( markDoubleClick() ) ); doubleClickAction->addTo( cornerMenu ); doubleClickAction->setEnabled( false ); rightClickAction = new QAction( tr("Next Click is Right Click"), QString::null, 0, 0 ); connect( rightClickAction, SIGNAL(activated()), canvas, SLOT( markRightClick() ) ); rightClickAction->addTo( cornerMenu ); rightClickAction->setEnabled( false ); } void KVNC::toggleFullScreen() { if ( fullscreen ) { canvas->releaseKeyboard(); canvas->reparent( stack, 0, QPoint(0,0), false ); canvas->setFrameStyle( QFrame::Panel | QFrame::Sunken ); setCentralWidget( stack ); stack->addWidget(canvas,get_unique_id()); stack->raiseWidget(canvas); canvas->show(); stack->show(); fullScreenAction->setText( tr("Full Screen") ); } else { canvas->setFrameStyle( QFrame::NoFrame ); stack->removeWidget(canvas); canvas->reparent( 0,WStyle_Tool | WStyle_Customize | WStyle_StaysOnTop, QPoint(0,0),false); canvas->resize(qApp->desktop()->width(), qApp->desktop()->height()); canvas->raise(); canvas->setFocus(); canvas->grabKeyboard(); canvas->show(); fullScreenAction->setText( tr("Stop Full Screen") ); } fullscreen = !fullscreen; } void KVNC::closeConnection() { if ( fullscreen ) toggleFullScreen(); canvas->closeConnection(); } void KVNC::showMenu() { QPoint pt = mapToGlobal(cornerButton->pos()); QSize s = cornerMenu->sizeHint(); pt.ry() -= s.height(); pt.rx() -= s.width(); cornerMenu->popup( pt ); } void KVNC::connected() { static QString msg = tr( "Connected to remote host" ); statusMessage( msg ); ctlAltDelAction->setEnabled(true); disconnectAction->setEnabled( true ); fullScreenAction->setEnabled( true ); doubleClickAction->setEnabled( false ); rightClickAction->setEnabled( true ); stack->raiseWidget(canvas); bar->hide(); } void KVNC::loggedIn() { static QString msg = tr( "Logged in to remote host" ); statusMessage( msg ); } void KVNC::disconnected() { if ( fullscreen ) toggleFullScreen(); static QString msg = tr( "Connection closed" ); statusMessage( msg ); ctlAltDelAction->setEnabled(false); disconnectAction->setEnabled( false ); fullScreenAction->setEnabled( false ); doubleClickAction->setEnabled( false ); rightClickAction->setEnabled( false ); stack->raiseWidget(bookmarkSelector); bar->show(); } void KVNC::statusMessage( const QString &m ) { Global::statusMessage( m ); } void KVNC::error( const QString &msg ) { statusMessage( msg ); QMessageBox::warning( this, tr("VNC Viewer"), msg ); } void KVNC::deleteBookmark(void) { bookmarkSelector->deleteBookmark(bookmarkSelector->selectedBookmark()); } |