source: vendor/synergy/current/lib/client/CServerProxy.cpp

Last change on this file was 2749, checked in by bird, 19 years ago

synergy v1.3.1 sources (zip).

File size: 18.4 KB
Line 
1/*
2 * synergy -- mouse and keyboard sharing utility
3 * Copyright (C) 2002 Chris Schoeneman
4 *
5 * This package is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU General Public License
7 * found in the file COPYING that should have accompanied this file.
8 *
9 * This package is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
13 */
14
15#include "CServerProxy.h"
16#include "CClient.h"
17#include "CClipboard.h"
18#include "CProtocolUtil.h"
19#include "OptionTypes.h"
20#include "ProtocolTypes.h"
21#include "IStream.h"
22#include "CLog.h"
23#include "IEventQueue.h"
24#include "TMethodEventJob.h"
25#include "XBase.h"
26#include <memory>
27
28//
29// CServerProxy
30//
31
32CServerProxy::CServerProxy(CClient* client, IStream* stream) :
33 m_client(client),
34 m_stream(stream),
35 m_seqNum(0),
36 m_compressMouse(false),
37 m_compressMouseRelative(false),
38 m_xMouse(0),
39 m_yMouse(0),
40 m_dxMouse(0),
41 m_dyMouse(0),
42 m_ignoreMouse(false),
43 m_keepAliveAlarm(0.0),
44 m_keepAliveAlarmTimer(NULL),
45 m_parser(&CServerProxy::parseHandshakeMessage)
46{
47 assert(m_client != NULL);
48 assert(m_stream != NULL);
49
50 // initialize modifier translation table
51 for (KeyModifierID id = 0; id < kKeyModifierIDLast; ++id)
52 m_modifierTranslationTable[id] = id;
53
54 // handle data on stream
55 EVENTQUEUE->adoptHandler(IStream::getInputReadyEvent(),
56 m_stream->getEventTarget(),
57 new TMethodEventJob<CServerProxy>(this,
58 &CServerProxy::handleData));
59
60 // send heartbeat
61 setKeepAliveRate(kKeepAliveRate);
62}
63
64CServerProxy::~CServerProxy()
65{
66 setKeepAliveRate(-1.0);
67 EVENTQUEUE->removeHandler(IStream::getInputReadyEvent(),
68 m_stream->getEventTarget());
69}
70
71void
72CServerProxy::resetKeepAliveAlarm()
73{
74 if (m_keepAliveAlarmTimer != NULL) {
75 EVENTQUEUE->removeHandler(CEvent::kTimer, m_keepAliveAlarmTimer);
76 EVENTQUEUE->deleteTimer(m_keepAliveAlarmTimer);
77 m_keepAliveAlarmTimer = NULL;
78 }
79 if (m_keepAliveAlarm > 0.0) {
80 m_keepAliveAlarmTimer =
81 EVENTQUEUE->newOneShotTimer(m_keepAliveAlarm, NULL);
82 EVENTQUEUE->adoptHandler(CEvent::kTimer, m_keepAliveAlarmTimer,
83 new TMethodEventJob<CServerProxy>(this,
84 &CServerProxy::handleKeepAliveAlarm));
85 }
86}
87
88void
89CServerProxy::setKeepAliveRate(double rate)
90{
91 m_keepAliveAlarm = rate * kKeepAlivesUntilDeath;
92 resetKeepAliveAlarm();
93}
94
95void
96CServerProxy::handleData(const CEvent&, void*)
97{
98 // handle messages until there are no more. first read message code.
99 UInt8 code[4];
100 UInt32 n = m_stream->read(code, 4);
101 while (n != 0) {
102 // verify we got an entire code
103 if (n != 4) {
104 LOG((CLOG_ERR "incomplete message from server: %d bytes", n));
105 m_client->disconnect("incomplete message from server");
106 return;
107 }
108
109 // parse message
110 LOG((CLOG_DEBUG2 "msg from server: %c%c%c%c", code[0], code[1], code[2], code[3]));
111 switch ((this->*m_parser)(code)) {
112 case kOkay:
113 break;
114
115 case kUnknown:
116 LOG((CLOG_ERR "invalid message from server: %c%c%c%c", code[0], code[1], code[2], code[3]));
117 m_client->disconnect("invalid message from server");
118 return;
119
120 case kDisconnect:
121 return;
122 }
123
124 // next message
125 n = m_stream->read(code, 4);
126 }
127
128 flushCompressedMouse();
129}
130
131CServerProxy::EResult
132CServerProxy::parseHandshakeMessage(const UInt8* code)
133{
134 if (memcmp(code, kMsgQInfo, 4) == 0) {
135 queryInfo();
136 }
137
138 else if (memcmp(code, kMsgCInfoAck, 4) == 0) {
139 infoAcknowledgment();
140 }
141
142 else if (memcmp(code, kMsgDSetOptions, 4) == 0) {
143 setOptions();
144
145 // handshake is complete
146 m_parser = &CServerProxy::parseMessage;
147 m_client->handshakeComplete();
148 }
149
150 else if (memcmp(code, kMsgCResetOptions, 4) == 0) {
151 resetOptions();
152 }
153
154 else if (memcmp(code, kMsgCKeepAlive, 4) == 0) {
155 // echo keep alives and reset alarm
156 CProtocolUtil::writef(m_stream, kMsgCKeepAlive);
157 resetKeepAliveAlarm();
158 }
159
160 else if (memcmp(code, kMsgCNoop, 4) == 0) {
161 // accept and discard no-op
162 }
163
164 else if (memcmp(code, kMsgCClose, 4) == 0) {
165 // server wants us to hangup
166 LOG((CLOG_DEBUG1 "recv close"));
167 m_client->disconnect(NULL);
168 return kDisconnect;
169 }
170
171 else if (memcmp(code, kMsgEIncompatible, 4) == 0) {
172 SInt32 major, minor;
173 CProtocolUtil::readf(m_stream,
174 kMsgEIncompatible + 4, &major, &minor);
175 LOG((CLOG_ERR "server has incompatible version %d.%d", major, minor));
176 m_client->disconnect("server has incompatible version");
177 return kDisconnect;
178 }
179
180 else if (memcmp(code, kMsgEBusy, 4) == 0) {
181 LOG((CLOG_ERR "server already has a connected client with name \"%s\"", m_client->getName().c_str()));
182 m_client->disconnect("server already has a connected client with our name");
183 return kDisconnect;
184 }
185
186 else if (memcmp(code, kMsgEUnknown, 4) == 0) {
187 LOG((CLOG_ERR "server refused client with name \"%s\"", m_client->getName().c_str()));
188 m_client->disconnect("server refused client with our name");
189 return kDisconnect;
190 }
191
192 else if (memcmp(code, kMsgEBad, 4) == 0) {
193 LOG((CLOG_ERR "server disconnected due to a protocol error"));
194 m_client->disconnect("server reported a protocol error");
195 return kDisconnect;
196 }
197 else {
198 return kUnknown;
199 }
200
201 return kOkay;
202}
203
204CServerProxy::EResult
205CServerProxy::parseMessage(const UInt8* code)
206{
207 if (memcmp(code, kMsgDMouseMove, 4) == 0) {
208 mouseMove();
209 }
210
211 else if (memcmp(code, kMsgDMouseRelMove, 4) == 0) {
212 mouseRelativeMove();
213 }
214
215 else if (memcmp(code, kMsgDMouseWheel, 4) == 0) {
216 mouseWheel();
217 }
218
219 else if (memcmp(code, kMsgDKeyDown, 4) == 0) {
220 keyDown();
221 }
222
223 else if (memcmp(code, kMsgDKeyUp, 4) == 0) {
224 keyUp();
225 }
226
227 else if (memcmp(code, kMsgDMouseDown, 4) == 0) {
228 mouseDown();
229 }
230
231 else if (memcmp(code, kMsgDMouseUp, 4) == 0) {
232 mouseUp();
233 }
234
235 else if (memcmp(code, kMsgDKeyRepeat, 4) == 0) {
236 keyRepeat();
237 }
238
239 else if (memcmp(code, kMsgCKeepAlive, 4) == 0) {
240 // echo keep alives and reset alarm
241 CProtocolUtil::writef(m_stream, kMsgCKeepAlive);
242 resetKeepAliveAlarm();
243 }
244
245 else if (memcmp(code, kMsgCNoop, 4) == 0) {
246 // accept and discard no-op
247 }
248
249 else if (memcmp(code, kMsgCEnter, 4) == 0) {
250 enter();
251 }
252
253 else if (memcmp(code, kMsgCLeave, 4) == 0) {
254 leave();
255 }
256
257 else if (memcmp(code, kMsgCClipboard, 4) == 0) {
258 grabClipboard();
259 }
260
261 else if (memcmp(code, kMsgCScreenSaver, 4) == 0) {
262 screensaver();
263 }
264
265 else if (memcmp(code, kMsgQInfo, 4) == 0) {
266 queryInfo();
267 }
268
269 else if (memcmp(code, kMsgCInfoAck, 4) == 0) {
270 infoAcknowledgment();
271 }
272
273 else if (memcmp(code, kMsgDClipboard, 4) == 0) {
274 setClipboard();
275 }
276
277 else if (memcmp(code, kMsgCResetOptions, 4) == 0) {
278 resetOptions();
279 }
280
281 else if (memcmp(code, kMsgDSetOptions, 4) == 0) {
282 setOptions();
283 }
284
285 else if (memcmp(code, kMsgCClose, 4) == 0) {
286 // server wants us to hangup
287 LOG((CLOG_DEBUG1 "recv close"));
288 m_client->disconnect(NULL);
289 return kDisconnect;
290 }
291 else if (memcmp(code, kMsgEBad, 4) == 0) {
292 LOG((CLOG_ERR "server disconnected due to a protocol error"));
293 m_client->disconnect("server reported a protocol error");
294 return kDisconnect;
295 }
296 else {
297 return kUnknown;
298 }
299
300 // send a reply. this is intended to work around a delay when
301 // running a linux server and an OS X (any BSD?) client. the
302 // client waits to send an ACK (if the system control flag
303 // net.inet.tcp.delayed_ack is 1) in hopes of piggybacking it
304 // on a data packet. we provide that packet here. i don't
305 // know why a delayed ACK should cause the server to wait since
306 // TCP_NODELAY is enabled.
307 CProtocolUtil::writef(m_stream, kMsgCNoop);
308
309 return kOkay;
310}
311
312void
313CServerProxy::handleKeepAliveAlarm(const CEvent&, void*)
314{
315 LOG((CLOG_NOTE "server is dead"));
316 m_client->disconnect("server is not responding");
317}
318
319void
320CServerProxy::onInfoChanged()
321{
322 // ignore mouse motion until we receive acknowledgment of our info
323 // change message.
324 m_ignoreMouse = true;
325
326 // send info update
327 queryInfo();
328}
329
330bool
331CServerProxy::onGrabClipboard(ClipboardID id)
332{
333 LOG((CLOG_DEBUG1 "sending clipboard %d changed", id));
334 CProtocolUtil::writef(m_stream, kMsgCClipboard, id, m_seqNum);
335 return true;
336}
337
338void
339CServerProxy::onClipboardChanged(ClipboardID id, const IClipboard* clipboard)
340{
341 CString data = IClipboard::marshall(clipboard);
342 LOG((CLOG_DEBUG1 "sending clipboard %d seqnum=%d, size=%d", id, m_seqNum, data.size()));
343 CProtocolUtil::writef(m_stream, kMsgDClipboard, id, m_seqNum, &data);
344}
345
346void
347CServerProxy::flushCompressedMouse()
348{
349 if (m_compressMouse) {
350 m_compressMouse = false;
351 m_client->mouseMove(m_xMouse, m_yMouse);
352 }
353 if (m_compressMouseRelative) {
354 m_compressMouseRelative = false;
355 m_client->mouseRelativeMove(m_dxMouse, m_dyMouse);
356 m_dxMouse = 0;
357 m_dyMouse = 0;
358 }
359}
360
361void
362CServerProxy::sendInfo(const CClientInfo& info)
363{
364 LOG((CLOG_DEBUG1 "sending info shape=%d,%d %dx%d", info.m_x, info.m_y, info.m_w, info.m_h));
365 CProtocolUtil::writef(m_stream, kMsgDInfo,
366 info.m_x, info.m_y,
367 info.m_w, info.m_h, 0,
368 info.m_mx, info.m_my);
369}
370
371KeyID
372CServerProxy::translateKey(KeyID id) const
373{
374 static const KeyID s_translationTable[kKeyModifierIDLast][2] = {
375 { kKeyNone, kKeyNone },
376 { kKeyShift_L, kKeyShift_R },
377 { kKeyControl_L, kKeyControl_R },
378 { kKeyAlt_L, kKeyAlt_R },
379 { kKeyMeta_L, kKeyMeta_R },
380 { kKeySuper_L, kKeySuper_R }
381 };
382
383 KeyModifierID id2 = kKeyModifierIDNull;
384 UInt32 side = 0;
385 switch (id) {
386 case kKeyShift_L:
387 id2 = kKeyModifierIDShift;
388 side = 0;
389 break;
390
391 case kKeyShift_R:
392 id2 = kKeyModifierIDShift;
393 side = 1;
394 break;
395
396 case kKeyControl_L:
397 id2 = kKeyModifierIDControl;
398 side = 0;
399 break;
400
401 case kKeyControl_R:
402 id2 = kKeyModifierIDControl;
403 side = 1;
404 break;
405
406 case kKeyAlt_L:
407 id2 = kKeyModifierIDAlt;
408 side = 0;
409 break;
410
411 case kKeyAlt_R:
412 id2 = kKeyModifierIDAlt;
413 side = 1;
414 break;
415
416 case kKeyMeta_L:
417 id2 = kKeyModifierIDMeta;
418 side = 0;
419 break;
420
421 case kKeyMeta_R:
422 id2 = kKeyModifierIDMeta;
423 side = 1;
424 break;
425
426 case kKeySuper_L:
427 id2 = kKeyModifierIDSuper;
428 side = 0;
429 break;
430
431 case kKeySuper_R:
432 id2 = kKeyModifierIDSuper;
433 side = 1;
434 break;
435 }
436
437 if (id2 != kKeyModifierIDNull) {
438 return s_translationTable[m_modifierTranslationTable[id2]][side];
439 }
440 else {
441 return id;
442 }
443}
444
445KeyModifierMask
446CServerProxy::translateModifierMask(KeyModifierMask mask) const
447{
448 static const KeyModifierMask s_masks[kKeyModifierIDLast] = {
449 0x0000,
450 KeyModifierShift,
451 KeyModifierControl,
452 KeyModifierAlt,
453 KeyModifierMeta,
454 KeyModifierSuper
455 };
456
457 KeyModifierMask newMask = mask & ~(KeyModifierShift |
458 KeyModifierControl |
459 KeyModifierAlt |
460 KeyModifierMeta |
461 KeyModifierSuper);
462 if ((mask & KeyModifierShift) != 0) {
463 newMask |= s_masks[m_modifierTranslationTable[kKeyModifierIDShift]];
464 }
465 if ((mask & KeyModifierControl) != 0) {
466 newMask |= s_masks[m_modifierTranslationTable[kKeyModifierIDControl]];
467 }
468 if ((mask & KeyModifierAlt) != 0) {
469 newMask |= s_masks[m_modifierTranslationTable[kKeyModifierIDAlt]];
470 }
471 if ((mask & KeyModifierMeta) != 0) {
472 newMask |= s_masks[m_modifierTranslationTable[kKeyModifierIDMeta]];
473 }
474 if ((mask & KeyModifierSuper) != 0) {
475 newMask |= s_masks[m_modifierTranslationTable[kKeyModifierIDSuper]];
476 }
477 return newMask;
478}
479
480void
481CServerProxy::enter()
482{
483 // parse
484 SInt16 x, y;
485 UInt16 mask;
486 UInt32 seqNum;
487 CProtocolUtil::readf(m_stream, kMsgCEnter + 4, &x, &y, &seqNum, &mask);
488 LOG((CLOG_DEBUG1 "recv enter, %d,%d %d %04x", x, y, seqNum, mask));
489
490 // discard old compressed mouse motion, if any
491 m_compressMouse = false;
492 m_compressMouseRelative = false;
493 m_dxMouse = 0;
494 m_dyMouse = 0;
495 m_seqNum = seqNum;
496
497 // forward
498 m_client->enter(x, y, seqNum, static_cast<KeyModifierMask>(mask), false);
499}
500
501void
502CServerProxy::leave()
503{
504 // parse
505 LOG((CLOG_DEBUG1 "recv leave"));
506
507 // send last mouse motion
508 flushCompressedMouse();
509
510 // forward
511 m_client->leave();
512}
513
514void
515CServerProxy::setClipboard()
516{
517 // parse
518 ClipboardID id;
519 UInt32 seqNum;
520 CString data;
521 CProtocolUtil::readf(m_stream, kMsgDClipboard + 4, &id, &seqNum, &data);
522 LOG((CLOG_DEBUG "recv clipboard %d size=%d", id, data.size()));
523
524 // validate
525 if (id >= kClipboardEnd) {
526 return;
527 }
528
529 // forward
530 CClipboard clipboard;
531 clipboard.unmarshall(data, 0);
532 m_client->setClipboard(id, &clipboard);
533}
534
535void
536CServerProxy::grabClipboard()
537{
538 // parse
539 ClipboardID id;
540 UInt32 seqNum;
541 CProtocolUtil::readf(m_stream, kMsgCClipboard + 4, &id, &seqNum);
542 LOG((CLOG_DEBUG "recv grab clipboard %d", id));
543
544 // validate
545 if (id >= kClipboardEnd) {
546 return;
547 }
548
549 // forward
550 m_client->grabClipboard(id);
551}
552
553void
554CServerProxy::keyDown()
555{
556 // get mouse up to date
557 flushCompressedMouse();
558
559 // parse
560 UInt16 id, mask, button;
561 CProtocolUtil::readf(m_stream, kMsgDKeyDown + 4, &id, &mask, &button);
562 LOG((CLOG_DEBUG1 "recv key down id=0x%08x, mask=0x%04x, button=0x%04x", id, mask, button));
563
564 // translate
565 KeyID id2 = translateKey(static_cast<KeyID>(id));
566 KeyModifierMask mask2 = translateModifierMask(
567 static_cast<KeyModifierMask>(mask));
568 if (id2 != static_cast<KeyID>(id) ||
569 mask2 != static_cast<KeyModifierMask>(mask))
570 LOG((CLOG_DEBUG1 "key down translated to id=0x%08x, mask=0x%04x", id2, mask2));
571
572 // forward
573 m_client->keyDown(id2, mask2, button);
574}
575
576void
577CServerProxy::keyRepeat()
578{
579 // get mouse up to date
580 flushCompressedMouse();
581
582 // parse
583 UInt16 id, mask, count, button;
584 CProtocolUtil::readf(m_stream, kMsgDKeyRepeat + 4,
585 &id, &mask, &count, &button);
586 LOG((CLOG_DEBUG1 "recv key repeat id=0x%08x, mask=0x%04x, count=%d, button=0x%04x", id, mask, count, button));
587
588 // translate
589 KeyID id2 = translateKey(static_cast<KeyID>(id));
590 KeyModifierMask mask2 = translateModifierMask(
591 static_cast<KeyModifierMask>(mask));
592 if (id2 != static_cast<KeyID>(id) ||
593 mask2 != static_cast<KeyModifierMask>(mask))
594 LOG((CLOG_DEBUG1 "key repeat translated to id=0x%08x, mask=0x%04x", id2, mask2));
595
596 // forward
597 m_client->keyRepeat(id2, mask2, count, button);
598}
599
600void
601CServerProxy::keyUp()
602{
603 // get mouse up to date
604 flushCompressedMouse();
605
606 // parse
607 UInt16 id, mask, button;
608 CProtocolUtil::readf(m_stream, kMsgDKeyUp + 4, &id, &mask, &button);
609 LOG((CLOG_DEBUG1 "recv key up id=0x%08x, mask=0x%04x, button=0x%04x", id, mask, button));
610
611 // translate
612 KeyID id2 = translateKey(static_cast<KeyID>(id));
613 KeyModifierMask mask2 = translateModifierMask(
614 static_cast<KeyModifierMask>(mask));
615 if (id2 != static_cast<KeyID>(id) ||
616 mask2 != static_cast<KeyModifierMask>(mask))
617 LOG((CLOG_DEBUG1 "key up translated to id=0x%08x, mask=0x%04x", id2, mask2));
618
619 // forward
620 m_client->keyUp(id2, mask2, button);
621}
622
623void
624CServerProxy::mouseDown()
625{
626 // get mouse up to date
627 flushCompressedMouse();
628
629 // parse
630 SInt8 id;
631 CProtocolUtil::readf(m_stream, kMsgDMouseDown + 4, &id);
632 LOG((CLOG_DEBUG1 "recv mouse down id=%d", id));
633
634 // forward
635 m_client->mouseDown(static_cast<ButtonID>(id));
636}
637
638void
639CServerProxy::mouseUp()
640{
641 // get mouse up to date
642 flushCompressedMouse();
643
644 // parse
645 SInt8 id;
646 CProtocolUtil::readf(m_stream, kMsgDMouseUp + 4, &id);
647 LOG((CLOG_DEBUG1 "recv mouse up id=%d", id));
648
649 // forward
650 m_client->mouseUp(static_cast<ButtonID>(id));
651}
652
653void
654CServerProxy::mouseMove()
655{
656 // parse
657 bool ignore;
658 SInt16 x, y;
659 CProtocolUtil::readf(m_stream, kMsgDMouseMove + 4, &x, &y);
660
661 // note if we should ignore the move
662 ignore = m_ignoreMouse;
663
664 // compress mouse motion events if more input follows
665 if (!ignore && !m_compressMouse && m_stream->isReady()) {
666 m_compressMouse = true;
667 }
668
669 // if compressing then ignore the motion but record it
670 if (m_compressMouse) {
671 m_compressMouseRelative = false;
672 ignore = true;
673 m_xMouse = x;
674 m_yMouse = y;
675 m_dxMouse = 0;
676 m_dyMouse = 0;
677 }
678 LOG((CLOG_DEBUG2 "recv mouse move %d,%d", x, y));
679
680 // forward
681 if (!ignore) {
682 m_client->mouseMove(x, y);
683 }
684}
685
686void
687CServerProxy::mouseRelativeMove()
688{
689 // parse
690 bool ignore;
691 SInt16 dx, dy;
692 CProtocolUtil::readf(m_stream, kMsgDMouseRelMove + 4, &dx, &dy);
693
694 // note if we should ignore the move
695 ignore = m_ignoreMouse;
696
697 // compress mouse motion events if more input follows
698 if (!ignore && !m_compressMouseRelative && m_stream->isReady()) {
699 m_compressMouseRelative = true;
700 }
701
702 // if compressing then ignore the motion but record it
703 if (m_compressMouseRelative) {
704 ignore = true;
705 m_dxMouse += dx;
706 m_dyMouse += dy;
707 }
708 LOG((CLOG_DEBUG2 "recv mouse relative move %d,%d", dx, dy));
709
710 // forward
711 if (!ignore) {
712 m_client->mouseRelativeMove(dx, dy);
713 }
714}
715
716void
717CServerProxy::mouseWheel()
718{
719 // get mouse up to date
720 flushCompressedMouse();
721
722 // parse
723 SInt16 xDelta, yDelta;
724 CProtocolUtil::readf(m_stream, kMsgDMouseWheel + 4, &xDelta, &yDelta);
725 LOG((CLOG_DEBUG2 "recv mouse wheel %+d,%+d", xDelta, yDelta));
726
727 // forward
728 m_client->mouseWheel(xDelta, yDelta);
729}
730
731void
732CServerProxy::screensaver()
733{
734 // parse
735 SInt8 on;
736 CProtocolUtil::readf(m_stream, kMsgCScreenSaver + 4, &on);
737 LOG((CLOG_DEBUG1 "recv screen saver on=%d", on));
738
739 // forward
740 m_client->screensaver(on != 0);
741}
742
743void
744CServerProxy::resetOptions()
745{
746 // parse
747 LOG((CLOG_DEBUG1 "recv reset options"));
748
749 // forward
750 m_client->resetOptions();
751
752 // reset keep alive
753 setKeepAliveRate(kKeepAliveRate);
754
755 // reset modifier translation table
756 for (KeyModifierID id = 0; id < kKeyModifierIDLast; ++id) {
757 m_modifierTranslationTable[id] = id;
758 }
759}
760
761void
762CServerProxy::setOptions()
763{
764 // parse
765 COptionsList options;
766 CProtocolUtil::readf(m_stream, kMsgDSetOptions + 4, &options);
767 LOG((CLOG_DEBUG1 "recv set options size=%d", options.size()));
768
769 // forward
770 m_client->setOptions(options);
771
772 // update modifier table
773 for (UInt32 i = 0, n = options.size(); i < n; i += 2) {
774 KeyModifierID id = kKeyModifierIDNull;
775 if (options[i] == kOptionModifierMapForShift) {
776 id = kKeyModifierIDShift;
777 }
778 else if (options[i] == kOptionModifierMapForControl) {
779 id = kKeyModifierIDControl;
780 }
781 else if (options[i] == kOptionModifierMapForAlt) {
782 id = kKeyModifierIDAlt;
783 }
784 else if (options[i] == kOptionModifierMapForMeta) {
785 id = kKeyModifierIDMeta;
786 }
787 else if (options[i] == kOptionModifierMapForSuper) {
788 id = kKeyModifierIDSuper;
789 }
790 else if (options[i] == kOptionHeartbeat) {
791 // update keep alive
792 setKeepAliveRate(1.0e-3 * static_cast<double>(options[i + 1]));
793 }
794 if (id != kKeyModifierIDNull) {
795 m_modifierTranslationTable[id] =
796 static_cast<KeyModifierID>(options[i + 1]);
797 LOG((CLOG_DEBUG1 "modifier %d mapped to %d", id, m_modifierTranslationTable[id]));
798 }
799 }
800}
801
802void
803CServerProxy::queryInfo()
804{
805 CClientInfo info;
806 m_client->getShape(info.m_x, info.m_y, info.m_w, info.m_h);
807 m_client->getCursorPos(info.m_mx, info.m_my);
808 sendInfo(info);
809}
810
811void
812CServerProxy::infoAcknowledgment()
813{
814 LOG((CLOG_DEBUG1 "recv info acknowledgment"));
815 m_ignoreMouse = false;
816}
Note: See TracBrowser for help on using the repository browser.