00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
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
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
00052 for (KeyModifierID id = 0; id < kKeyModifierIDLast; ++id)
00053 m_modifierTranslationTable[id] = id;
00054
00055
00056 EVENTQUEUE->adoptHandler(IStream::getInputReadyEvent(),
00057 m_stream->getEventTarget(),
00058 new TMethodEventJob<CServerProxy>(this,
00059 &CServerProxy::handleData));
00060
00061
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
00100 UInt8 code[4];
00101 UInt32 n = m_stream->read(code, 4);
00102 while (n != 0) {
00103
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
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
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
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
00157 CProtocolUtil::writef(m_stream, kMsgCKeepAlive);
00158 resetKeepAliveAlarm();
00159 }
00160
00161 else if (memcmp(code, kMsgCNoop, 4) == 0) {
00162
00163 }
00164
00165 else if (memcmp(code, kMsgCClose, 4) == 0) {
00166
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
00242 CProtocolUtil::writef(m_stream, kMsgCKeepAlive);
00243 resetKeepAliveAlarm();
00244 }
00245
00246 else if (memcmp(code, kMsgCNoop, 4) == 0) {
00247
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
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
00302
00303
00304
00305
00306
00307
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
00324
00325 m_ignoreMouse = true;
00326
00327
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
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
00492 m_compressMouse = false;
00493 m_compressMouseRelative = false;
00494 m_dxMouse = 0;
00495 m_dyMouse = 0;
00496 m_seqNum = seqNum;
00497
00498
00499 m_client->enter(x, y, seqNum, static_cast<KeyModifierMask>(mask), false);
00500 }
00501
00502 void
00503 CServerProxy::leave()
00504 {
00505
00506 LOG((CLOG_DEBUG1 "recv leave"));
00507
00508
00509 flushCompressedMouse();
00510
00511
00512 m_client->leave();
00513 }
00514
00515 void
00516 CServerProxy::setClipboard()
00517 {
00518
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
00526 if (id >= kClipboardEnd) {
00527 return;
00528 }
00529
00530
00531 CClipboard clipboard;
00532 clipboard.unmarshall(data, 0);
00533 m_client->setClipboard(id, &clipboard);
00534 }
00535
00536 void
00537 CServerProxy::grabClipboard()
00538 {
00539
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
00546 if (id >= kClipboardEnd) {
00547 return;
00548 }
00549
00550
00551 m_client->grabClipboard(id);
00552 }
00553
00554 void
00555 CServerProxy::keyDown()
00556 {
00557
00558 flushCompressedMouse();
00559
00560
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
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
00574 m_client->keyDown(id2, mask2, button);
00575 }
00576
00577 void
00578 CServerProxy::keyRepeat()
00579 {
00580
00581 flushCompressedMouse();
00582
00583
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
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
00598 m_client->keyRepeat(id2, mask2, count, button);
00599 }
00600
00601 void
00602 CServerProxy::keyUp()
00603 {
00604
00605 flushCompressedMouse();
00606
00607
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
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
00621 m_client->keyUp(id2, mask2, button);
00622 }
00623
00624 void
00625 CServerProxy::mouseDown()
00626 {
00627
00628 flushCompressedMouse();
00629
00630
00631 SInt8 id;
00632 CProtocolUtil::readf(m_stream, kMsgDMouseDown + 4, &id);
00633 LOG((CLOG_DEBUG1 "recv mouse down id=%d", id));
00634
00635
00636 m_client->mouseDown(static_cast<ButtonID>(id));
00637 }
00638
00639 void
00640 CServerProxy::mouseUp()
00641 {
00642
00643 flushCompressedMouse();
00644
00645
00646 SInt8 id;
00647 CProtocolUtil::readf(m_stream, kMsgDMouseUp + 4, &id);
00648 LOG((CLOG_DEBUG1 "recv mouse up id=%d", id));
00649
00650
00651 m_client->mouseUp(static_cast<ButtonID>(id));
00652 }
00653
00654 void
00655 CServerProxy::mouseMove()
00656 {
00657
00658 bool ignore;
00659 SInt16 x, y;
00660 CProtocolUtil::readf(m_stream, kMsgDMouseMove + 4, &x, &y);
00661
00662
00663 ignore = m_ignoreMouse;
00664
00665
00666 if (!ignore && !m_compressMouse && m_stream->isReady()) {
00667 m_compressMouse = true;
00668 }
00669
00670
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
00682 if (!ignore) {
00683 m_client->mouseMove(x, y);
00684 }
00685 }
00686
00687 void
00688 CServerProxy::mouseRelativeMove()
00689 {
00690
00691 bool ignore;
00692 SInt16 dx, dy;
00693 CProtocolUtil::readf(m_stream, kMsgDMouseRelMove + 4, &dx, &dy);
00694
00695
00696 ignore = m_ignoreMouse;
00697
00698
00699 if (!ignore && !m_compressMouseRelative && m_stream->isReady()) {
00700 m_compressMouseRelative = true;
00701 }
00702
00703
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
00712 if (!ignore) {
00713 m_client->mouseRelativeMove(dx, dy);
00714 }
00715 }
00716
00717 void
00718 CServerProxy::mouseWheel()
00719 {
00720
00721 flushCompressedMouse();
00722
00723
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
00729 m_client->mouseWheel(xDelta, yDelta);
00730 }
00731
00732 void
00733 CServerProxy::screensaver()
00734 {
00735
00736 SInt8 on;
00737 CProtocolUtil::readf(m_stream, kMsgCScreenSaver + 4, &on);
00738 LOG((CLOG_DEBUG1 "recv screen saver on=%d", on));
00739
00740
00741 m_client->screensaver(on != 0);
00742 }
00743
00744 void
00745 CServerProxy::resetOptions()
00746 {
00747
00748 LOG((CLOG_DEBUG1 "recv reset options"));
00749
00750
00751 m_client->resetOptions();
00752
00753
00754 setKeepAliveRate(kKeepAliveRate);
00755
00756
00757 for (KeyModifierID id = 0; id < kKeyModifierIDLast; ++id) {
00758 m_modifierTranslationTable[id] = id;
00759 }
00760 }
00761
00762 void
00763 CServerProxy::setOptions()
00764 {
00765
00766 COptionsList options;
00767 CProtocolUtil::readf(m_stream, kMsgDSetOptions + 4, &options);
00768 LOG((CLOG_DEBUG1 "recv set options size=%d", options.size()));
00769
00770
00771 m_client->setOptions(options);
00772
00773
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
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 }