summaryrefslogtreecommitdiff
authortreke <treke>2002-12-22 00:58:46 (UTC)
committer treke <treke>2002-12-22 00:58:46 (UTC)
commit17d7f11b16b650f6ee2b5c440506167ea41fbfe5 (patch) (side-by-side diff)
treecd5924c9e374a82c1cac6433dce098f3f45f4286
parent6853d02989fc01e5a65048aca9749c20e0f5d095 (diff)
downloadopie-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.
Diffstat (more/less context) (ignore whitespace changes)
-rw-r--r--noncore/comm/keypebble/krfbcanvas.cpp4
-rw-r--r--noncore/comm/keypebble/krfbdecoder.cpp5
-rw-r--r--noncore/comm/keypebble/kvnc.cpp3
3 files changed, 6 insertions, 6 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)
{
- openConnection(item->text());
+ 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());
}