CServerProxy.cpp

00001 /*
00002  * synergy -- mouse and keyboard sharing utility
00003  * Copyright (C) 2002 Chris Schoeneman
00004  * 
00005  * This package is free software; you can redistribute it and/or
00006  * modify it under the terms of the GNU General Public License
00007  * found in the file COPYING that should have accompanied this file.
00008  * 
00009  * This package is distributed in the hope that it will be useful,
00010  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00011  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00012  * GNU General Public License for more details.
00013  */
00014 
00015 #include "CServerProxy.h"
00016 #include "CClient.h"
00017 #include "CClipboard.h"
00018 #include "CProtocolUtil.h"
00019 #include "OptionTypes.h"
00020 #include "ProtocolTypes.h"
00021 #include "IStream.h"
00022 #include "CLog.h"
00023 #include "IEventQueue.h"
00024 #include "TMethodEventJob.h"
00025 #include "XBase.h"
00026 #include <memory>
00027 #include <cstring>
00028 
00029 //
00030 // CServerProxy
00031 //
00032 
00033 CServerProxy::CServerProxy(CClient* client, IStream* stream) :
00034     m_client(client),
00035     m_stream(stream),
00036     m_seqNum(0),
00037     m_compressMouse(false),
00038     m_compressMouseRelative(false),
00039     m_xMouse(0),
00040     m_yMouse(0),
00041     m_dxMouse(0),
00042     m_dyMouse(0),
00043     m_ignoreMouse(false),
00044     m_keepAliveAlarm(0.0),
00045     m_keepAliveAlarmTimer(NULL),
00046     m_parser(&CServerProxy::parseHandshakeMessage)
00047 {
00048     assert(m_client != NULL);
00049     assert(m_stream != NULL);
00050 
00051     // initialize modifier translation table
00052     for (KeyModifierID id = 0; id < kKeyModifierIDLast; ++id)
00053         m_modifierTranslationTable[id] = id;
00054 
00055     // handle data on stream
00056     EVENTQUEUE->adoptHandler(IStream::getInputReadyEvent(),
00057                             m_stream->getEventTarget(),
00058                             new TMethodEventJob<CServerProxy>(this,
00059                                 &CServerProxy::handleData));
00060 
00061     // send heartbeat
00062     setKeepAliveRate(kKeepAliveRate);
00063 }
00064 
00065 CServerProxy::~CServerProxy()
00066 {
00067     setKeepAliveRate(-1.0);
00068     EVENTQUEUE->removeHandler(IStream::getInputReadyEvent(),
00069                             m_stream->getEventTarget());
00070 }
00071 
00072 void
00073 CServerProxy::resetKeepAliveAlarm()
00074 {
00075     if (m_keepAliveAlarmTimer != NULL) {
00076         EVENTQUEUE->removeHandler(CEvent::kTimer, m_keepAliveAlarmTimer);
00077         EVENTQUEUE->deleteTimer(m_keepAliveAlarmTimer);
00078         m_keepAliveAlarmTimer = NULL;
00079     }
00080     if (m_keepAliveAlarm > 0.0) {
00081         m_keepAliveAlarmTimer =
00082             EVENTQUEUE->newOneShotTimer(m_keepAliveAlarm, NULL);
00083         EVENTQUEUE->adoptHandler(CEvent::kTimer, m_keepAliveAlarmTimer,
00084                             new TMethodEventJob<CServerProxy>(this,
00085                                 &CServerProxy::handleKeepAliveAlarm));
00086     }
00087 }
00088 
00089 void
00090 CServerProxy::setKeepAliveRate(double rate)
00091 {
00092     m_keepAliveAlarm = rate * kKeepAlivesUntilDeath;
00093     resetKeepAliveAlarm();
00094 }
00095 
00096 void
00097 CServerProxy::handleData(const CEvent&, void*)
00098 {
00099     // handle messages until there are no more.  first read message code.
00100     UInt8 code[4];
00101     UInt32 n = m_stream->read(code, 4);
00102     while (n != 0) {
00103         // verify we got an entire code
00104         if (n != 4) {
00105             LOG((CLOG_ERR "incomplete message from server: %d bytes", n));
00106             m_client->disconnect("incomplete message from server");
00107             return;
00108         }
00109 
00110         // parse message
00111         LOG((CLOG_DEBUG2 "msg from server: %c%c%c%c", code[0], code[1], code[2], code[3]));
00112         switch ((this->*m_parser)(code)) {
00113         case kOkay:
00114             break;
00115 
00116         case kUnknown:
00117             LOG((CLOG_ERR "invalid message from server: %c%c%c%c", code[0], code[1], code[2], code[3]));
00118             m_client->disconnect("invalid message from server");
00119             return;
00120 
00121         case kDisconnect:
00122             return;
00123         }
00124 
00125         // next message
00126         n = m_stream->read(code, 4);
00127     }
00128 
00129     flushCompressedMouse();
00130 }
00131 
00132 CServerProxy::EResult
00133 CServerProxy::parseHandshakeMessage(const UInt8* code)
00134 {
00135     if (memcmp(code, kMsgQInfo, 4) == 0) {
00136         queryInfo();
00137     }
00138 
00139     else if (memcmp(code, kMsgCInfoAck, 4) == 0) {
00140         infoAcknowledgment();
00141     }
00142 
00143     else if (memcmp(code, kMsgDSetOptions, 4) == 0) {
00144         setOptions();
00145 
00146         // handshake is complete
00147         m_parser = &CServerProxy::parseMessage;
00148         m_client->handshakeComplete();
00149     }
00150 
00151     else if (memcmp(code, kMsgCResetOptions, 4) == 0) {
00152         resetOptions();
00153     }
00154 
00155     else if (memcmp(code, kMsgCKeepAlive, 4) == 0) {
00156         // echo keep alives and reset alarm
00157         CProtocolUtil::writef(m_stream, kMsgCKeepAlive);
00158         resetKeepAliveAlarm();
00159     }
00160 
00161     else if (memcmp(code, kMsgCNoop, 4) == 0) {
00162         // accept and discard no-op
00163     }
00164 
00165     else if (memcmp(code, kMsgCClose, 4) == 0) {
00166         // server wants us to hangup
00167         LOG((CLOG_DEBUG1 "recv close"));
00168         m_client->disconnect(NULL);
00169         return kDisconnect;
00170     }
00171 
00172     else if (memcmp(code, kMsgEIncompatible, 4) == 0) {
00173         SInt32 major, minor;
00174         CProtocolUtil::readf(m_stream,
00175                         kMsgEIncompatible + 4, &major, &minor);
00176         LOG((CLOG_ERR "server has incompatible version %d.%d", major, minor));
00177         m_client->disconnect("server has incompatible version");
00178         return kDisconnect;
00179     }
00180 
00181     else if (memcmp(code, kMsgEBusy, 4) == 0) {
00182         LOG((CLOG_ERR "server already has a connected client with name \"%s\"", m_client->getName().c_str()));
00183         m_client->disconnect("server already has a connected client with our name");
00184         return kDisconnect;
00185     }
00186 
00187     else if (memcmp(code, kMsgEUnknown, 4) == 0) {
00188         LOG((CLOG_ERR "server refused client with name \"%s\"", m_client->getName().c_str()));
00189         m_client->disconnect("server refused client with our name");
00190         return kDisconnect;
00191     }
00192 
00193     else if (memcmp(code, kMsgEBad, 4) == 0) {
00194         LOG((CLOG_ERR "server disconnected due to a protocol error"));
00195         m_client->disconnect("server reported a protocol error");
00196         return kDisconnect;
00197     }
00198     else {
00199         return kUnknown;
00200     }
00201 
00202     return kOkay;
00203 }
00204 
00205 CServerProxy::EResult
00206 CServerProxy::parseMessage(const UInt8* code)
00207 {
00208     if (memcmp(code, kMsgDMouseMove, 4) == 0) {
00209         mouseMove();
00210     }
00211 
00212     else if (memcmp(code, kMsgDMouseRelMove, 4) == 0) {
00213         mouseRelativeMove();
00214     }
00215 
00216     else if (memcmp(code, kMsgDMouseWheel, 4) == 0) {
00217         mouseWheel();
00218     }
00219 
00220     else if (memcmp(code, kMsgDKeyDown, 4) == 0) {
00221         keyDown();
00222     }
00223 
00224     else if (memcmp(code, kMsgDKeyUp, 4) == 0) {
00225         keyUp();
00226     }
00227 
00228     else if (memcmp(code, kMsgDMouseDown, 4) == 0) {
00229         mouseDown();
00230     }
00231 
00232     else if (memcmp(code, kMsgDMouseUp, 4) == 0) {
00233         mouseUp();
00234     }
00235 
00236     else if (memcmp(code, kMsgDKeyRepeat, 4) == 0) {
00237         keyRepeat();
00238     }
00239 
00240     else if (memcmp(code, kMsgCKeepAlive, 4) == 0) {
00241         // echo keep alives and reset alarm
00242         CProtocolUtil::writef(m_stream, kMsgCKeepAlive);
00243         resetKeepAliveAlarm();
00244     }
00245 
00246     else if (memcmp(code, kMsgCNoop, 4) == 0) {
00247         // accept and discard no-op
00248     }
00249 
00250     else if (memcmp(code, kMsgCEnter, 4) == 0) {
00251         enter();
00252     }
00253 
00254     else if (memcmp(code, kMsgCLeave, 4) == 0) {
00255         leave();
00256     }
00257 
00258     else if (memcmp(code, kMsgCClipboard, 4) == 0) {
00259         grabClipboard();
00260     }
00261 
00262     else if (memcmp(code, kMsgCScreenSaver, 4) == 0) {
00263         screensaver();
00264     }
00265 
00266     else if (memcmp(code, kMsgQInfo, 4) == 0) {
00267         queryInfo();
00268     }
00269 
00270     else if (memcmp(code, kMsgCInfoAck, 4) == 0) {
00271         infoAcknowledgment();
00272     }
00273 
00274     else if (memcmp(code, kMsgDClipboard, 4) == 0) {
00275         setClipboard();
00276     }
00277 
00278     else if (memcmp(code, kMsgCResetOptions, 4) == 0) {
00279         resetOptions();
00280     }
00281 
00282     else if (memcmp(code, kMsgDSetOptions, 4) == 0) {
00283         setOptions();
00284     }
00285 
00286     else if (memcmp(code, kMsgCClose, 4) == 0) {
00287         // server wants us to hangup
00288         LOG((CLOG_DEBUG1 "recv close"));
00289         m_client->disconnect(NULL);
00290         return kDisconnect;
00291     }
00292     else if (memcmp(code, kMsgEBad, 4) == 0) {
00293         LOG((CLOG_ERR "server disconnected due to a protocol error"));
00294         m_client->disconnect("server reported a protocol error");
00295         return kDisconnect;
00296     }
00297     else {
00298         return kUnknown;
00299     }
00300 
00301     // send a reply.  this is intended to work around a delay when
00302     // running a linux server and an OS X (any BSD?) client.  the
00303     // client waits to send an ACK (if the system control flag
00304     // net.inet.tcp.delayed_ack is 1) in hopes of piggybacking it
00305     // on a data packet.  we provide that packet here.  i don't
00306     // know why a delayed ACK should cause the server to wait since
00307     // TCP_NODELAY is enabled.
00308     CProtocolUtil::writef(m_stream, kMsgCNoop);
00309 
00310     return kOkay;
00311 }
00312 
00313 void
00314 CServerProxy::handleKeepAliveAlarm(const CEvent&, void*)
00315 {
00316     LOG((CLOG_NOTE "server is dead"));
00317     m_client->disconnect("server is not responding");
00318 }
00319 
00320 void
00321 CServerProxy::onInfoChanged()
00322 {
00323     // ignore mouse motion until we receive acknowledgment of our info
00324     // change message.
00325     m_ignoreMouse = true;
00326 
00327     // send info update
00328     queryInfo();
00329 }
00330 
00331 bool
00332 CServerProxy::onGrabClipboard(ClipboardID id)
00333 {
00334     LOG((CLOG_DEBUG1 "sending clipboard %d changed", id));
00335     CProtocolUtil::writef(m_stream, kMsgCClipboard, id, m_seqNum);
00336     return true;
00337 }
00338 
00339 void
00340 CServerProxy::onClipboardChanged(ClipboardID id, const IClipboard* clipboard)
00341 {
00342     CString data = IClipboard::marshall(clipboard);
00343     LOG((CLOG_DEBUG1 "sending clipboard %d seqnum=%d, size=%d", id, m_seqNum, data.size()));
00344     CProtocolUtil::writef(m_stream, kMsgDClipboard, id, m_seqNum, &data);
00345 }
00346 
00347 void
00348 CServerProxy::flushCompressedMouse()
00349 {
00350     if (m_compressMouse) {
00351         m_compressMouse = false;
00352         m_client->mouseMove(m_xMouse, m_yMouse);
00353     }
00354     if (m_compressMouseRelative) {
00355         m_compressMouseRelative = false;
00356         m_client->mouseRelativeMove(m_dxMouse, m_dyMouse);
00357         m_dxMouse = 0;
00358         m_dyMouse = 0;
00359     }
00360 }
00361 
00362 void
00363 CServerProxy::sendInfo(const CClientInfo& info)
00364 {
00365     LOG((CLOG_DEBUG1 "sending info shape=%d,%d %dx%d", info.m_x, info.m_y, info.m_w, info.m_h));
00366     CProtocolUtil::writef(m_stream, kMsgDInfo,
00367                                 info.m_x, info.m_y,
00368                                 info.m_w, info.m_h, 0,
00369                                 info.m_mx, info.m_my);
00370 }
00371 
00372 KeyID
00373 CServerProxy::translateKey(KeyID id) const
00374 {
00375     static const KeyID s_translationTable[kKeyModifierIDLast][2] = {
00376         { kKeyNone,      kKeyNone },
00377         { kKeyShift_L,   kKeyShift_R },
00378         { kKeyControl_L, kKeyControl_R },
00379         { kKeyAlt_L,     kKeyAlt_R },
00380         { kKeyMeta_L,    kKeyMeta_R },
00381         { kKeySuper_L,   kKeySuper_R }
00382     };
00383 
00384     KeyModifierID id2 = kKeyModifierIDNull;
00385     UInt32 side      = 0;
00386     switch (id) {
00387     case kKeyShift_L:
00388         id2  = kKeyModifierIDShift;
00389         side = 0;
00390         break;
00391 
00392     case kKeyShift_R:
00393         id2  = kKeyModifierIDShift;
00394         side = 1;
00395         break;
00396 
00397     case kKeyControl_L:
00398         id2  = kKeyModifierIDControl;
00399         side = 0;
00400         break;
00401 
00402     case kKeyControl_R:
00403         id2  = kKeyModifierIDControl;
00404         side = 1;
00405         break;
00406 
00407     case kKeyAlt_L:
00408         id2  = kKeyModifierIDAlt;
00409         side = 0;
00410         break;
00411 
00412     case kKeyAlt_R:
00413         id2  = kKeyModifierIDAlt;
00414         side = 1;
00415         break;
00416 
00417     case kKeyMeta_L:
00418         id2  = kKeyModifierIDMeta;
00419         side = 0;
00420         break;
00421 
00422     case kKeyMeta_R:
00423         id2  = kKeyModifierIDMeta;
00424         side = 1;
00425         break;
00426 
00427     case kKeySuper_L:
00428         id2  = kKeyModifierIDSuper;
00429         side = 0;
00430         break;
00431 
00432     case kKeySuper_R:
00433         id2  = kKeyModifierIDSuper;
00434         side = 1;
00435         break;
00436     }
00437 
00438     if (id2 != kKeyModifierIDNull) {
00439         return s_translationTable[m_modifierTranslationTable[id2]][side];
00440     }
00441     else {
00442         return id;
00443     }
00444 }
00445 
00446 KeyModifierMask
00447 CServerProxy::translateModifierMask(KeyModifierMask mask) const
00448 {
00449     static const KeyModifierMask s_masks[kKeyModifierIDLast] = {
00450         0x0000,
00451         KeyModifierShift,
00452         KeyModifierControl,
00453         KeyModifierAlt,
00454         KeyModifierMeta,
00455         KeyModifierSuper
00456     };
00457 
00458     KeyModifierMask newMask = mask & ~(KeyModifierShift |
00459                                         KeyModifierControl |
00460                                         KeyModifierAlt |
00461                                         KeyModifierMeta |
00462                                         KeyModifierSuper);
00463     if ((mask & KeyModifierShift) != 0) {
00464         newMask |= s_masks[m_modifierTranslationTable[kKeyModifierIDShift]];
00465     }
00466     if ((mask & KeyModifierControl) != 0) {
00467         newMask |= s_masks[m_modifierTranslationTable[kKeyModifierIDControl]];
00468     }
00469     if ((mask & KeyModifierAlt) != 0) {
00470         newMask |= s_masks[m_modifierTranslationTable[kKeyModifierIDAlt]];
00471     }
00472     if ((mask & KeyModifierMeta) != 0) {
00473         newMask |= s_masks[m_modifierTranslationTable[kKeyModifierIDMeta]];
00474     }
00475     if ((mask & KeyModifierSuper) != 0) {
00476         newMask |= s_masks[m_modifierTranslationTable[kKeyModifierIDSuper]];
00477     }
00478     return newMask;
00479 }
00480 
00481 void
00482 CServerProxy::enter()
00483 {
00484     // parse
00485     SInt16 x, y;
00486     UInt16 mask;
00487     UInt32 seqNum;
00488     CProtocolUtil::readf(m_stream, kMsgCEnter + 4, &x, &y, &seqNum, &mask);
00489     LOG((CLOG_DEBUG1 "recv enter, %d,%d %d %04x", x, y, seqNum, mask));
00490 
00491     // discard old compressed mouse motion, if any
00492     m_compressMouse         = false;
00493     m_compressMouseRelative = false;
00494     m_dxMouse               = 0;
00495     m_dyMouse               = 0;
00496     m_seqNum                = seqNum;
00497 
00498     // forward
00499     m_client->enter(x, y, seqNum, static_cast<KeyModifierMask>(mask), false);
00500 }
00501 
00502 void
00503 CServerProxy::leave()
00504 {
00505     // parse
00506     LOG((CLOG_DEBUG1 "recv leave"));
00507 
00508     // send last mouse motion
00509     flushCompressedMouse();
00510 
00511     // forward
00512     m_client->leave();
00513 }
00514 
00515 void
00516 CServerProxy::setClipboard()
00517 {
00518     // parse
00519     ClipboardID id;
00520     UInt32 seqNum;
00521     CString data;
00522     CProtocolUtil::readf(m_stream, kMsgDClipboard + 4, &id, &seqNum, &data);
00523     LOG((CLOG_DEBUG "recv clipboard %d size=%d", id, data.size()));
00524 
00525     // validate
00526     if (id >= kClipboardEnd) {
00527         return;
00528     }
00529 
00530     // forward
00531     CClipboard clipboard;
00532     clipboard.unmarshall(data, 0);
00533     m_client->setClipboard(id, &clipboard);
00534 }
00535 
00536 void
00537 CServerProxy::grabClipboard()
00538 {
00539     // parse
00540     ClipboardID id;
00541     UInt32 seqNum;
00542     CProtocolUtil::readf(m_stream, kMsgCClipboard + 4, &id, &seqNum);
00543     LOG((CLOG_DEBUG "recv grab clipboard %d", id));
00544 
00545     // validate
00546     if (id >= kClipboardEnd) {
00547         return;
00548     }
00549 
00550     // forward
00551     m_client->grabClipboard(id);
00552 }
00553 
00554 void
00555 CServerProxy::keyDown()
00556 {
00557     // get mouse up to date
00558     flushCompressedMouse();
00559 
00560     // parse
00561     UInt16 id, mask, button;
00562     CProtocolUtil::readf(m_stream, kMsgDKeyDown + 4, &id, &mask, &button);
00563     LOG((CLOG_DEBUG1 "recv key down id=0x%08x, mask=0x%04x, button=0x%04x", id, mask, button));
00564 
00565     // translate
00566     KeyID id2             = translateKey(static_cast<KeyID>(id));
00567     KeyModifierMask mask2 = translateModifierMask(
00568                                 static_cast<KeyModifierMask>(mask));
00569     if (id2   != static_cast<KeyID>(id) ||
00570         mask2 != static_cast<KeyModifierMask>(mask))
00571         LOG((CLOG_DEBUG1 "key down translated to id=0x%08x, mask=0x%04x", id2, mask2));
00572 
00573     // forward
00574     m_client->keyDown(id2, mask2, button);
00575 }
00576 
00577 void
00578 CServerProxy::keyRepeat()
00579 {
00580     // get mouse up to date
00581     flushCompressedMouse();
00582 
00583     // parse
00584     UInt16 id, mask, count, button;
00585     CProtocolUtil::readf(m_stream, kMsgDKeyRepeat + 4,
00586                                 &id, &mask, &count, &button);
00587     LOG((CLOG_DEBUG1 "recv key repeat id=0x%08x, mask=0x%04x, count=%d, button=0x%04x", id, mask, count, button));
00588 
00589     // translate
00590     KeyID id2             = translateKey(static_cast<KeyID>(id));
00591     KeyModifierMask mask2 = translateModifierMask(
00592                                 static_cast<KeyModifierMask>(mask));
00593     if (id2   != static_cast<KeyID>(id) ||
00594         mask2 != static_cast<KeyModifierMask>(mask))
00595         LOG((CLOG_DEBUG1 "key repeat translated to id=0x%08x, mask=0x%04x", id2, mask2));
00596 
00597     // forward
00598     m_client->keyRepeat(id2, mask2, count, button);
00599 }
00600 
00601 void
00602 CServerProxy::keyUp()
00603 {
00604     // get mouse up to date
00605     flushCompressedMouse();
00606 
00607     // parse
00608     UInt16 id, mask, button;
00609     CProtocolUtil::readf(m_stream, kMsgDKeyUp + 4, &id, &mask, &button);
00610     LOG((CLOG_DEBUG1 "recv key up id=0x%08x, mask=0x%04x, button=0x%04x", id, mask, button));
00611 
00612     // translate
00613     KeyID id2             = translateKey(static_cast<KeyID>(id));
00614     KeyModifierMask mask2 = translateModifierMask(
00615                                 static_cast<KeyModifierMask>(mask));
00616     if (id2   != static_cast<KeyID>(id) ||
00617         mask2 != static_cast<KeyModifierMask>(mask))
00618         LOG((CLOG_DEBUG1 "key up translated to id=0x%08x, mask=0x%04x", id2, mask2));
00619 
00620     // forward
00621     m_client->keyUp(id2, mask2, button);
00622 }
00623 
00624 void
00625 CServerProxy::mouseDown()
00626 {
00627     // get mouse up to date
00628     flushCompressedMouse();
00629 
00630     // parse
00631     SInt8 id;
00632     CProtocolUtil::readf(m_stream, kMsgDMouseDown + 4, &id);
00633     LOG((CLOG_DEBUG1 "recv mouse down id=%d", id));
00634 
00635     // forward
00636     m_client->mouseDown(static_cast<ButtonID>(id));
00637 }
00638 
00639 void
00640 CServerProxy::mouseUp()
00641 {
00642     // get mouse up to date
00643     flushCompressedMouse();
00644 
00645     // parse
00646     SInt8 id;
00647     CProtocolUtil::readf(m_stream, kMsgDMouseUp + 4, &id);
00648     LOG((CLOG_DEBUG1 "recv mouse up id=%d", id));
00649 
00650     // forward
00651     m_client->mouseUp(static_cast<ButtonID>(id));
00652 }
00653 
00654 void
00655 CServerProxy::mouseMove()
00656 {
00657     // parse
00658     bool ignore;
00659     SInt16 x, y;
00660     CProtocolUtil::readf(m_stream, kMsgDMouseMove + 4, &x, &y);
00661 
00662     // note if we should ignore the move
00663     ignore = m_ignoreMouse;
00664 
00665     // compress mouse motion events if more input follows
00666     if (!ignore && !m_compressMouse && m_stream->isReady()) {
00667         m_compressMouse = true;
00668     }
00669 
00670     // if compressing then ignore the motion but record it
00671     if (m_compressMouse) {
00672         m_compressMouseRelative = false;
00673         ignore    = true;
00674         m_xMouse  = x;
00675         m_yMouse  = y;
00676         m_dxMouse = 0;
00677         m_dyMouse = 0;
00678     }
00679     LOG((CLOG_DEBUG2 "recv mouse move %d,%d", x, y));
00680 
00681     // forward
00682     if (!ignore) {
00683         m_client->mouseMove(x, y);
00684     }
00685 }
00686 
00687 void
00688 CServerProxy::mouseRelativeMove()
00689 {
00690     // parse
00691     bool ignore;
00692     SInt16 dx, dy;
00693     CProtocolUtil::readf(m_stream, kMsgDMouseRelMove + 4, &dx, &dy);
00694 
00695     // note if we should ignore the move
00696     ignore = m_ignoreMouse;
00697 
00698     // compress mouse motion events if more input follows
00699     if (!ignore && !m_compressMouseRelative && m_stream->isReady()) {
00700         m_compressMouseRelative = true;
00701     }
00702 
00703     // if compressing then ignore the motion but record it
00704     if (m_compressMouseRelative) {
00705         ignore     = true;
00706         m_dxMouse += dx;
00707         m_dyMouse += dy;
00708     }
00709     LOG((CLOG_DEBUG2 "recv mouse relative move %d,%d", dx, dy));
00710 
00711     // forward
00712     if (!ignore) {
00713         m_client->mouseRelativeMove(dx, dy);
00714     }
00715 }
00716 
00717 void
00718 CServerProxy::mouseWheel()
00719 {
00720     // get mouse up to date
00721     flushCompressedMouse();
00722 
00723     // parse
00724     SInt16 xDelta, yDelta;
00725     CProtocolUtil::readf(m_stream, kMsgDMouseWheel + 4, &xDelta, &yDelta);
00726     LOG((CLOG_DEBUG2 "recv mouse wheel %+d,%+d", xDelta, yDelta));
00727 
00728     // forward
00729     m_client->mouseWheel(xDelta, yDelta);
00730 }
00731 
00732 void
00733 CServerProxy::screensaver()
00734 {
00735     // parse
00736     SInt8 on;
00737     CProtocolUtil::readf(m_stream, kMsgCScreenSaver + 4, &on);
00738     LOG((CLOG_DEBUG1 "recv screen saver on=%d", on));
00739 
00740     // forward
00741     m_client->screensaver(on != 0);
00742 }
00743 
00744 void
00745 CServerProxy::resetOptions()
00746 {
00747     // parse
00748     LOG((CLOG_DEBUG1 "recv reset options"));
00749 
00750     // forward
00751     m_client->resetOptions();
00752 
00753     // reset keep alive
00754     setKeepAliveRate(kKeepAliveRate);
00755 
00756     // reset modifier translation table
00757     for (KeyModifierID id = 0; id < kKeyModifierIDLast; ++id) {
00758         m_modifierTranslationTable[id] = id;
00759     }
00760 }
00761 
00762 void
00763 CServerProxy::setOptions()
00764 {
00765     // parse
00766     COptionsList options;
00767     CProtocolUtil::readf(m_stream, kMsgDSetOptions + 4, &options);
00768     LOG((CLOG_DEBUG1 "recv set options size=%d", options.size()));
00769 
00770     // forward
00771     m_client->setOptions(options);
00772 
00773     // update modifier table
00774     for (UInt32 i = 0, n = options.size(); i < n; i += 2) {
00775         KeyModifierID id = kKeyModifierIDNull;
00776         if (options[i] == kOptionModifierMapForShift) {
00777             id = kKeyModifierIDShift;
00778         }
00779         else if (options[i] == kOptionModifierMapForControl) {
00780             id = kKeyModifierIDControl;
00781         }
00782         else if (options[i] == kOptionModifierMapForAlt) {
00783             id = kKeyModifierIDAlt;
00784         }
00785         else if (options[i] == kOptionModifierMapForMeta) {
00786             id = kKeyModifierIDMeta;
00787         }
00788         else if (options[i] == kOptionModifierMapForSuper) {
00789             id = kKeyModifierIDSuper;
00790         }
00791         else if (options[i] == kOptionHeartbeat) {
00792             // update keep alive
00793             setKeepAliveRate(1.0e-3 * static_cast<double>(options[i + 1]));
00794         }
00795         if (id != kKeyModifierIDNull) {
00796             m_modifierTranslationTable[id] =
00797                 static_cast<KeyModifierID>(options[i + 1]);
00798             LOG((CLOG_DEBUG1 "modifier %d mapped to %d", id, m_modifierTranslationTable[id]));
00799         }
00800     }
00801 }
00802 
00803 void
00804 CServerProxy::queryInfo()
00805 {
00806     CClientInfo info;
00807     m_client->getShape(info.m_x, info.m_y, info.m_w, info.m_h);
00808     m_client->getCursorPos(info.m_mx, info.m_my);
00809     sendInfo(info);
00810 }
00811 
00812 void
00813 CServerProxy::infoAcknowledgment()
00814 {
00815     LOG((CLOG_DEBUG1 "recv info acknowledgment"));
00816     m_ignoreMouse = false;
00817 }

Generated on Fri Nov 6 00:18:45 2009 for synergy-plus by  doxygen 1.4.7