00001 #include "krfbconnection.h"
00002 #include "krfbserverinfo.h"
00003 #include "krfbdecoder.h"
00004 #include "krfbbuffer.h"
00005
00006
00007 #include <opie2/odebug.h>
00008 using namespace Opie::Core;
00009
00010
00011 #include <qpixmap.h>
00012
00013
00014 #include <assert.h>
00015
00016
00017
00018
00019
00020 const int endianTest = 1;
00021
00022
00023 #define Swap16IfLE(s) \
00024 (*(char *)&endianTest ? ((((s) & 0xff) << 8) | (((s) >> 8) & 0xff)) : (s))
00025
00026 #define Swap32IfLE(l) \
00027 (*(char *)&endianTest ? ((((l) & 0xff000000) >> 24) | \
00028 (((l) & 0x00ff0000) >> 8) | \
00029 (((l) & 0x0000ff00) << 8) | \
00030 (((l) & 0x000000ff) << 24)) : (l))
00031
00032
00033
00034
00035 const int ServerInitLength = 24;
00036 const int UpdateHeaderLength = 4;
00037 const int RectHeaderLength = 12;
00038 const int RectChunkSize = 4;
00039 const int CopyRectPosLength = 4;
00040 const int ServerCutLenLength = 7;
00041
00042
00043
00044
00045 static CARD8 SetPixelFormatId = 0;
00046
00047 static CARD8 SetEncodingsId = 2;
00048 static CARD8 UpdateRequestId = 3;
00049 static CARD8 KeyEventId = 4;
00050 static CARD8 PointerEventId = 5;
00051 static CARD8 ClientCutTextId = 6;
00052
00053
00054
00055
00056 static CARD8 UpdateId = 0;
00057 static CARD8 BellId = 2;
00058 static CARD8 ServerCutId = 3;
00059
00060
00061
00062
00063 static CARD32 RawEncoding = Swap32IfLE( 0 );
00064 static CARD32 CopyRectEncoding = Swap32IfLE(1 );
00065 static CARD32 RreEncoding = Swap32IfLE( 2 );
00066 static CARD32 CorreEncoding = Swap32IfLE( 4 );
00067 static CARD32 HexTileEncoding = Swap32IfLE( 5 );
00068
00069 static struct {
00070 int keysym;
00071 int keycode;
00072 } keyMap[] = {
00073 { 0xff08, Qt::Key_Backspace },
00074 { 0xff09, Qt::Key_Tab },
00075 { 0xff0d, Qt::Key_Return },
00076 { 0xff1b, Qt::Key_Escape },
00077 { 0xff63, Qt::Key_Insert },
00078 { 0xffff, Qt::Key_Delete },
00079 { 0xff50, Qt::Key_Home },
00080 { 0xff57, Qt::Key_End },
00081 { 0xff55, Qt::Key_Prior },
00082 { 0xff56, Qt::Key_Next },
00083 { 0xff51, Qt::Key_Left },
00084 { 0xff52, Qt::Key_Up },
00085 { 0xff53, Qt::Key_Right },
00086 { 0xff54, Qt::Key_Down },
00087 { 0xffbe, Qt::Key_F1 },
00088 { 0xffbf, Qt::Key_F2 },
00089 { 0xffc0, Qt::Key_F3 },
00090 { 0xffc1, Qt::Key_F4 },
00091 { 0xffc2, Qt::Key_F5 },
00092 { 0xffc3, Qt::Key_F6 },
00093 { 0xffc4, Qt::Key_F7 },
00094 { 0xffc5, Qt::Key_F8 },
00095 { 0xffc6, Qt::Key_F9 },
00096 { 0xffc7, Qt::Key_F10 },
00097 { 0xffc8, Qt::Key_F11 },
00098 { 0xffc9, Qt::Key_F12 },
00099 { 0xffe1, Qt::Key_Shift },
00100 { 0xffe2, Qt::Key_Shift },
00101 { 0xffe3, Qt::Key_Control },
00102 { 0xffe4, Qt::Key_Control },
00103 { 0xffe7, Qt::Key_Meta },
00104 { 0xffe8, Qt::Key_Meta },
00105 { 0xffe9, Qt::Key_Alt },
00106 { 0xffea, Qt::Key_Alt },
00107 { 0, 0 }
00108 };
00109
00110
00111 KRFBDecoder::KRFBDecoder( KRFBConnection *con )
00112 : QObject( con, "RFB Decoder" )
00113 {
00114 assert( con );
00115 assert( con->state() == KRFBConnection::Connected );
00116
00117 this->con = con;
00118 this->buf = 0;
00119 this->info = 0;
00120 this->format = 0;
00121 this->buttonMask = 0;
00122 currentState = Idle;
00123 }
00124
00125 KRFBDecoder::~KRFBDecoder()
00126 {
00127 if ( info )
00128 delete info;
00129 if ( format )
00130 delete format;
00131 }
00132
00133 void KRFBDecoder::start()
00134 {
00135 sendClientInit();
00136 }
00137
00138 void KRFBDecoder::sendClientInit()
00139 {
00140 con->write( &( con->options()->shared ), 1 );
00141
00142
00143 owarn << "Waiting for server init" << oendl;
00144
00145 static QString statusMsg = tr( "Waiting for server initialization..." );
00146 emit status( statusMsg );
00147
00148 currentState = AwaitingServerInit;
00149 connect( con, SIGNAL( gotEnoughData() ), SLOT( gotServerInit() ) );
00150 con->waitForData( ServerInitLength );
00151 }
00152
00153 void KRFBDecoder::gotServerInit()
00154 {
00155 owarn << "Got server init" << oendl;
00156 disconnect( con, SIGNAL( gotEnoughData() ), this, SLOT( gotServerInit() ) );
00157
00158 if ( info )
00159 delete info;
00160 info = new KRFBServerInfo;
00161 CHECK_PTR( info );
00162
00163 con->read( &(info->width), 2 );
00164 info->width = Swap16IfLE( info->width );
00165 con->read( &info->height, 2 );
00166 info->height = Swap16IfLE( info->height );
00167
00168 con->read( &(info->bpp), 1 );
00169 con->read( &(info->depth), 1 );
00170 con->read( &(info->bigEndian), 1 );
00171 con->read( &(info->trueColor), 1 );
00172
00173 con->read( &(info->redMax), 2 );
00174 info->redMax = Swap16IfLE( info->redMax );
00175 con->read( &(info->greenMax), 2 );
00176 info->greenMax = Swap16IfLE( info->greenMax );
00177 con->read( &(info->blueMax), 2 );
00178 info->blueMax = Swap16IfLE( info->blueMax );
00179
00180 con->read( &(info->redShift), 1 );
00181 con->read( &(info->greenShift), 1 );
00182 con->read( &(info->blueShift), 1 );
00183
00184 con->read( info->padding, 3 );
00185
00186 con->read( &(info->nameLength), 4 );
00187 info->nameLength = Swap32IfLE( info->nameLength );
00188
00189 owarn << "Width = " << info->width << ", Height = " << info->height << "" << oendl;
00190 owarn << "Bpp = " << info->bpp << ", Depth = " << info->depth << ", Big = " << info->bigEndian
00191 << ", True = " << info->trueColor << oendl;
00192 owarn << "RedMax = " << info->redMax << ", GreenMax = " << info->greenMax << ", BlueMax = " << info->blueMax << oendl;
00193 owarn << "RedShift = " << info->redShift << ", GreenShift = " << info->greenShift
00194 << ", BlueShift = " << info-> blueShift << oendl;
00195
00196 buf->resize( info->width/con->options()->scaleFactor, info->height /con->options()->scaleFactor);
00197
00198
00199 owarn << "Waiting for desktop name" << oendl;
00200
00201 static QString statusMsg = tr( "Waiting for desktop name..." );
00202 emit status( statusMsg );
00203
00204 currentState = AwaitingDesktopName;
00205 connect( con, SIGNAL( gotEnoughData() ), SLOT( gotDesktopName() ) );
00206 con->waitForData( info->nameLength );
00207 }
00208
00209 void KRFBDecoder::gotDesktopName()
00210 {
00211 assert( info );
00212 assert( currentState == AwaitingDesktopName );
00213
00214 owarn << "Got desktop name" << oendl;
00215
00216 disconnect( con, SIGNAL( gotEnoughData() ),
00217 this, SLOT( gotDesktopName() ) );
00218
00219 char *buf = new char[ info->nameLength + 1 ];
00220 CHECK_PTR( buf );
00221
00222 con->read( buf, info->nameLength );
00223 buf[ info->nameLength ] = '\0';
00224 info->name = buf;
00225
00226 owarn << "Desktop: " << info->name.latin1() << "" << oendl;
00227
00228 delete buf;
00229
00230
00231 decidePixelFormat();
00232 sendPixelFormat();
00233 sendAllowedEncodings();
00234 currentState = Idle;
00235
00236 QString msg;
00237 msg = tr( "Connected to %1" );
00238 msg = msg.arg( info->name );
00239 emit status( msg );
00240
00241 sendUpdateRequest( false );
00242 }
00243
00244 void KRFBDecoder::decidePixelFormat()
00245 {
00246 assert( info );
00247
00248 if ( format )
00249 delete format;
00250 format = new KRFBPixelFormat;
00251 CHECK_PTR( format );
00252
00253
00254
00255
00256
00257 int screenDepth = QPixmap::defaultDepth();
00258 int bestDepth = ( screenDepth > info->depth ) ? info->depth : screenDepth;
00259 int chosenDepth;
00260
00261 if ( con->options()->colors256 )
00262 chosenDepth = 8;
00263 else
00264 chosenDepth = bestDepth;
00265
00266 owarn << "Screen depth=" << screenDepth << ", server depth=" << info->depth
00267 << ", best depth=" << bestDepth << "eight bit " << con->options()->colors256
00268 << ", chosenDepth=" << chosenDepth << oendl;
00269
00270 format->depth = chosenDepth;
00271
00272
00273 if ( chosenDepth == info->depth ) {
00274
00275 format->bpp = info->bpp;
00276
00277 format->bigEndian = true;
00278 format->trueColor = info->trueColor;
00279 format->redMax = info->redMax;
00280 format->greenMax = info->greenMax;
00281 format->blueMax = info->blueMax;
00282 format->redShift = info->redShift;
00283 format->greenShift = info->greenShift;
00284 format->blueShift = info->blueShift;
00285 }
00286 else {
00287 if ( chosenDepth == 8 ) {
00288 format->bpp = 8;
00289 format->bigEndian = true;
00290 format->trueColor = true;
00291 format->redMax = 7;
00292 format->greenMax = 7;
00293 format->blueMax = 3;
00294 format->redShift = 0;
00295 format->greenShift = 3;
00296 format->blueShift = 6;
00297 }
00298 }
00299
00300 format->redMax = Swap16IfLE( format->redMax );
00301 format->greenMax = Swap16IfLE( format->greenMax );
00302 format->blueMax = Swap16IfLE( format->blueMax );
00303 }
00304
00305 void KRFBDecoder::sendPixelFormat()
00306 {
00307 static char padding[3];
00308 con->write( &SetPixelFormatId, 1 );
00309 con->write( padding, 3 );
00310
00311 con->write( &(format->bpp), 1 );
00312 con->write( &(format->depth), 1 );
00313 con->write( &(format->bigEndian), 1 );
00314 con->write( &(format->trueColor), 1 );
00315
00316 con->write( &(format->redMax), 2 );
00317 con->write( &(format->greenMax), 2 );
00318 con->write( &(format->blueMax), 2 );
00319
00320 con->write( &(format->redShift), 1 );
00321 con->write( &(format->greenShift), 1 );
00322 con->write( &(format->blueShift), 1 );
00323 con->write( format->padding, 3 );
00324 }
00325
00326 void KRFBDecoder::sendAllowedEncodings()
00327 {
00328 static CARD8 padding[1];
00329 con->write( &SetEncodingsId, 1 );
00330 con->write( padding, 1 );
00331
00332 CARD16 noEncodings = con->options()->encodings();
00333 noEncodings = Swap16IfLE( noEncodings );
00334 con->write( &noEncodings, 2 );
00335
00336 if ( con->options()->corre )
00337 con->write( &CorreEncoding, 4 );
00338 if ( con->options()->hexTile )
00339 con->write( &HexTileEncoding, 4 );
00340 if ( con->options()->rre )
00341 con->write( &RreEncoding, 4 );
00342 if ( con->options()->copyrect )
00343 con->write( &CopyRectEncoding, 4 );
00344
00345 con->write( &RawEncoding, 4 );
00346 }
00347
00348 void KRFBDecoder::sendUpdateRequest( bool incremental )
00349 {
00350 if ( currentState != Idle )
00351 return;
00352
00353 con->write( &UpdateRequestId, 1 );
00354 con->write( &incremental, 1 );
00355
00356 static CARD16 x = 0, y = 0;
00357 static CARD16 w = Swap16IfLE( info->width );
00358 static CARD16 h = Swap16IfLE( info->height );
00359
00360 con->write( &x, 2 );
00361 con->write( &y, 2 );
00362 con->write( &w, 2 );
00363 con->write( &h, 2 );
00364
00365
00366 currentState = AwaitingUpdate;
00367 connect( con, SIGNAL( gotEnoughData() ), SLOT( gotUpdateHeader() ) );
00368 con->waitForData( UpdateHeaderLength );
00369 }
00370
00371 void KRFBDecoder::gotUpdateHeader()
00372 {
00373 assert( currentState == AwaitingUpdate );
00374
00375
00376
00377 disconnect( con, SIGNAL( gotEnoughData() ),
00378 this, SLOT( gotUpdateHeader() ) );
00379
00380 CARD8 msgType;
00381 con->read( &msgType, 1 );
00382
00383 if ( msgType != UpdateId ) {
00384
00385 if ( msgType == ServerCutId ) {
00386 oldState = currentState;
00387 gotServerCut();
00388 }
00389 else if ( msgType == BellId ) {
00390 oldState = currentState;
00391 gotBell();
00392 }
00393 else {
00394 int msg = msgType;
00395 QString protocolError = tr( "Protocol Error: Message Id %1 was "
00396 "found when expecting an update "
00397 "message." ).arg( msg );
00398 currentState = Error;
00399 emit error( protocolError );
00400 }
00401 return;
00402 }
00403
00404 CARD8 padding;
00405 con->read( &padding, 1 );
00406
00407 con->read( &noRects, 2 );
00408 noRects = Swap16IfLE( noRects );
00409
00410
00411
00412
00413 currentState = AwaitingRectHeader;
00414 connect( con, SIGNAL( gotEnoughData() ), SLOT( gotRectHeader() ) );
00415 con->waitForData( RectHeaderLength );
00416 }
00417
00418 void KRFBDecoder::gotRectHeader()
00419 {
00420 assert( currentState == AwaitingRectHeader );
00421
00422
00423
00424 disconnect( con, SIGNAL( gotEnoughData() ),
00425 this, SLOT( gotRectHeader() ) );
00426
00427 con->read( &x, 2 );
00428 x = Swap16IfLE( x );
00429 con->read( &y, 2 );
00430 y = Swap16IfLE( y );
00431
00432 con->read( &w, 2 );
00433 w = Swap16IfLE( w );
00434 con->read( &h, 2 );
00435 h = Swap16IfLE( h );
00436
00437 con->read( &encoding, 4 );
00438
00439
00440
00441
00442
00443
00444
00445
00446
00447
00448
00449 if ( encoding == RawEncoding ) {
00450
00451 handleRawRect();
00452 }
00453 else if ( encoding == CopyRectEncoding ) {
00454
00455 handleCopyRect();
00456 }
00457 else if ( encoding == RreEncoding ) {
00458 owarn << "RRE encoding" << oendl;
00459 handleRRERect();
00460 }
00461 else if ( encoding == CorreEncoding ) {
00462 owarn << "CoRRE encoding" << oendl;
00463 handleCoRRERect();
00464 }
00465 else if ( encoding == HexTileEncoding ) {
00466 owarn << "HexTile encoding" << oendl;
00467 handleHexTileRect();
00468 }
00469 else {
00470 int msg = Swap32IfLE( encoding );
00471 QString protocolError = tr( "Protocol Error: An unknown encoding was "
00472 "used by the server %1" ).arg( msg );
00473 currentState = Error;
00474 owarn << "Unknown encoding, " << msg << "" << oendl;
00475 emit error( protocolError );
00476 return;
00477 }
00478 }
00479
00480
00481
00482
00483
00484 void KRFBDecoder::handleRawRect()
00485 {
00486
00487
00488
00489
00490
00491
00492
00493
00494 if ( h > RectChunkSize ) {
00495
00496
00497
00498
00499 getRawRectChunk( RectChunkSize );
00500
00501 }
00502 else {
00503 getRawRectChunk( h );
00504 }
00505 }
00506
00507 void KRFBDecoder::getRawRectChunk( int lines )
00508 {
00509 this->lines = lines;
00510 CARD32 count = lines * w * format->bpp / 8;
00511
00512
00513
00514
00515 currentState = AwaitingRawRectChunk;
00516 connect( con, SIGNAL( gotEnoughData() ), SLOT( gotRawRectChunk() ) );
00517 con->waitForData( count );
00518 }
00519
00520 void KRFBDecoder::gotRawRectChunk()
00521 {
00522 assert( currentState == AwaitingRawRectChunk );
00523
00524 disconnect( con, SIGNAL( gotEnoughData() ),
00525 this, SLOT( gotRawRectChunk() ) );
00526
00527
00528
00529
00530
00531
00532
00533
00534 int count = lines * w * format->bpp / 8;
00535 char *hack = new char[ count ];
00536 con->read( hack, count );
00537 buf->drawRawRectChunk( hack, x, y, w, lines );
00538 delete hack;
00539
00540
00541 h = h - lines;
00542 y = y + lines;
00543
00544 if ( h > 0 ) {
00545 handleRawRect();
00546 }
00547 else {
00548 noRects--;
00549
00550
00551
00552 if ( noRects ) {
00553 currentState = AwaitingRectHeader;
00554 connect( con, SIGNAL( gotEnoughData() ), SLOT( gotRectHeader() ) );
00555 con->waitForData( RectHeaderLength );
00556 }
00557 else {
00558
00559 currentState = Idle;
00560 sendUpdateRequest (1);
00561 }
00562 }
00563 }
00564
00565
00566
00567
00568
00569 void KRFBDecoder::handleCopyRect()
00570 {
00571 currentState = AwaitingCopyRectPos;
00572 connect( con, SIGNAL( gotEnoughData() ), SLOT( gotCopyRectPos() ) );
00573 con->waitForData( CopyRectPosLength );
00574 }
00575
00576 void KRFBDecoder::gotCopyRectPos()
00577 {
00578 disconnect( con, SIGNAL( gotEnoughData() ),
00579 this, SLOT( gotCopyRectPos() ) );
00580
00581 CARD16 srcX;
00582 CARD16 srcY;
00583
00584 con->read( &srcX, 2 );
00585 con->read( &srcY, 2 );
00586
00587 srcX = Swap16IfLE( srcX );
00588 srcY = Swap16IfLE( srcY );
00589
00590 buf->copyRect( srcX, srcY, x, y, w, h );
00591
00592 noRects--;
00593
00594
00595
00596 if ( noRects ) {
00597 currentState = AwaitingRectHeader;
00598 connect( con, SIGNAL( gotEnoughData() ), SLOT( gotRectHeader() ) );
00599 con->waitForData( RectHeaderLength );
00600 }
00601 else
00602 currentState = Idle;
00603 }
00604
00605 void KRFBDecoder::handleRRERect()
00606 {
00607 owarn << "RRE not implemented" << oendl;
00608 }
00609
00610 void KRFBDecoder::handleCoRRERect()
00611 {
00612 owarn << "CoRRE not implemented" << oendl;
00613 }
00614
00615 void KRFBDecoder::handleHexTileRect()
00616 {
00617 owarn << "HexTile not implemented" << oendl;
00618 }
00619
00620 void KRFBDecoder::sendMouseEvent( QMouseEvent *e )
00621 {
00622
00623 if ( e->type() != QEvent::MouseMove ) {
00624 buttonMask = 0;
00625 if ( e->type() == QEvent::MouseButtonPress ) {
00626 if ( e->button() & LeftButton )
00627 buttonMask |= 0x01;
00628 if ( e->button() & MidButton )
00629 buttonMask |= 0x04;
00630 if ( e->button() & RightButton )
00631 buttonMask |= 0x02;
00632 }
00633 else if ( e->type() == QEvent::MouseButtonRelease ) {
00634 if ( e->button() & LeftButton )
00635 buttonMask &= 0x06;
00636 if ( e->button() & MidButton )
00637 buttonMask |= 0x03;
00638 if ( e->button() & RightButton )
00639 buttonMask |= 0x05;
00640 }
00641 }
00642
00643
00644 CARD16 x = Swap16IfLE( e->x() * con->options()->scaleFactor );
00645 CARD16 y = Swap16IfLE( e->y() * con->options()->scaleFactor );
00646
00647 con->write( &PointerEventId, 1 );
00648 con->write( &buttonMask, 1 );
00649 con->write( &x, 2 );
00650 con->write( &y, 2 );
00651 }
00652
00653
00654 void KRFBDecoder::sendCutEvent( const QString &unicode )
00655 {
00656
00657
00658
00659
00660
00661
00662
00663
00664 CARD8 padding[3];
00665 QCString text = unicode.local8Bit();
00666 CARD32 length = text.length();
00667 length = Swap32IfLE( length );
00668
00669 con->write( &ClientCutTextId, 1 );
00670 con->write( &padding, 3 );
00671 con->write( &length, 4 );
00672 con->write( text.data(), length );
00673 }
00674
00675 void KRFBDecoder::gotServerCut()
00676 {
00677 owarn << "Got server cut" << oendl;
00678
00679 currentState = AwaitingServerCutLength;
00680 connect( con, SIGNAL( gotEnoughData() ), SLOT( gotServerCutLength() ) );
00681 con->waitForData( ServerCutLenLength );
00682 }
00683
00684 void KRFBDecoder::gotServerCutLength()
00685 {
00686 assert( currentState = AwaitingServerCutLength );
00687 disconnect( con, SIGNAL( gotEnoughData() ),
00688 this, SLOT( gotServerCutLength() ) );
00689
00690 CARD8 padding[3];
00691 con->read( padding, 3 );
00692
00693 con->read( &serverCutTextLen, 4 );
00694 serverCutTextLen = Swap32IfLE( serverCutTextLen );
00695
00696 currentState = AwaitingServerCutText;
00697 connect( con, SIGNAL( gotEnoughData() ), SLOT( gotServerCutText() ) );
00698 con->waitForData( serverCutTextLen );
00699 }
00700
00701 void KRFBDecoder::gotServerCutText()
00702 {
00703 assert( currentState = AwaitingServerCutText );
00704
00705 disconnect( con, SIGNAL( gotEnoughData() ),
00706 this, SLOT( gotServerCutText() ) );
00707
00708
00709
00710
00711
00712
00713
00714
00715
00716
00717 char *cutbuf = new char[ serverCutTextLen + 1 ];
00718 CHECK_PTR( cutbuf );
00719
00720 con->read( cutbuf, serverCutTextLen );
00721 cutbuf[ serverCutTextLen ] = '\0';
00722
00723
00724
00725
00726
00727
00728
00729
00730
00731 delete cutbuf;
00732
00733 if ( oldState == AwaitingUpdate ) {
00734 currentState = AwaitingUpdate;
00735 connect( con, SIGNAL( gotEnoughData() ), SLOT( gotUpdateHeader() ) );
00736 con->waitForData( UpdateHeaderLength );
00737 }
00738 else if ( oldState == Idle ) {
00739 currentState = Idle;
00740 }
00741 else {
00742 owarn << "Async handled in weird state" << oendl;
00743 currentState = oldState;
00744 };
00745 }
00746
00747 void KRFBDecoder::gotBell()
00748 {
00749 owarn << "Got server bell" << oendl;
00750 buf->soundBell();
00751
00752
00753 if ( oldState == AwaitingUpdate ) {
00754 currentState = AwaitingUpdate;
00755 connect( con, SIGNAL( gotEnoughData() ), SLOT( gotUpdateHeader() ) );
00756 con->waitForData( UpdateHeaderLength );
00757 }
00758 else if ( oldState == Idle ) {
00759 currentState = Idle;
00760 }
00761 else {
00762 owarn << "Async handled in weird state" << oendl;
00763 currentState = oldState;
00764 };
00765 }
00766
00767 void KRFBDecoder::sendKeyPressEvent( QKeyEvent *event )
00768 {
00769 int key;
00770 key = toKeySym( event );
00771 if ( key ) {
00772 key = Swap32IfLE( key );
00773
00774 CARD8 mask = true;
00775
00776 CARD16 padding = 0;
00777 con->write( &KeyEventId, 1 );
00778 con->write( &mask, 1 );
00779 con->write( &padding, 2 );
00780 con->write( &key, 4 );
00781 }
00782 }
00783
00784 void KRFBDecoder::sendKeyReleaseEvent( QKeyEvent *event )
00785 {
00786 int key;
00787 key = toKeySym( event );
00788 if ( key ) {
00789 key = Swap32IfLE( key );
00790
00791 CARD8 mask = false;
00792
00793 CARD16 padding = 0;
00794 con->write( &KeyEventId, 1 );
00795 con->write( &mask, 1 );
00796 con->write( &padding, 2 );
00797 con->write( &key, 4 );
00798 }
00799 }
00800
00801
00802
00803
00804
00805
00806
00807
00808
00809
00810
00811 int KRFBDecoder::toKeySym( QKeyEvent *k )
00812 {
00813
00814
00815
00816
00817 if ((k->key() >= Qt::Key_Escape) && (k->key() <= Qt::Key_F12)) {
00818 for(int i = 0; keyMap[i].keycode != 0; i++) {
00819 if (k->key() == keyMap[i].keycode) {
00820 return keyMap[i].keysym;
00821 }
00822 }
00823 }
00824
00825
00826
00827
00828
00829
00830 return k->ascii();
00831 }