CServer.h

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 #ifndef CSERVER_H
00016 #define CSERVER_H
00017 
00018 #include "CConfig.h"
00019 #include "CClipboard.h"
00020 #include "ClipboardTypes.h"
00021 #include "KeyTypes.h"
00022 #include "MouseTypes.h"
00023 #include "CEvent.h"
00024 #include "CStopwatch.h"
00025 #include "stdmap.h"
00026 #include "stdset.h"
00027 #include "stdvector.h"
00028 
00029 class CBaseClientProxy;
00030 class CEventQueueTimer;
00031 class CPrimaryClient;
00032 class CInputFilter;
00033 
00035 
00038 class CServer {
00039 public:
00041     class CLockCursorToScreenInfo {
00042     public:
00043         enum State { kOff, kOn, kToggle };
00044 
00045         static CLockCursorToScreenInfo* alloc(State state = kToggle);
00046 
00047     public:
00048         State           m_state;
00049     };
00050 
00052     class CSwitchToScreenInfo {
00053     public:
00054         static CSwitchToScreenInfo* alloc(const CString& screen);
00055 
00056     public:
00057         // this is a C-string;  this type is a variable size structure
00058         char            m_screen[1];
00059     };
00060 
00062     class CSwitchInDirectionInfo {
00063     public:
00064         static CSwitchInDirectionInfo* alloc(EDirection direction);
00065 
00066     public:
00067         EDirection      m_direction;
00068     };
00069 
00071     class CScreenConnectedInfo {
00072     public:
00073         static CScreenConnectedInfo* alloc(const CString& screen);
00074 
00075     public:
00076         // this is a C-string;  this type is a variable size structure
00077         char            m_screen[1];
00078     };
00079 
00081     class CKeyboardBroadcastInfo {
00082     public:
00083         enum State { kOff, kOn, kToggle };
00084 
00085         static CKeyboardBroadcastInfo* alloc(State state = kToggle);
00086         static CKeyboardBroadcastInfo* alloc(State state,
00087                                             const CString& screens);
00088 
00089     public:
00090         State           m_state;
00091         char            m_screens[1];
00092     };
00093 
00099     CServer(const CConfig& config, CPrimaryClient* primaryClient);
00100     ~CServer();
00101 
00103 
00104 
00106 
00111     bool                setConfig(const CConfig&);
00112 
00114 
00118     void                adoptClient(CBaseClientProxy* client);
00119 
00121 
00127     void                disconnect();
00128 
00130 
00131 
00132 
00134 
00137     UInt32              getNumClients() const;
00138 
00140 
00143     void                getClients(std::vector<CString>& list) const;
00144 
00146 
00150     static CEvent::Type getErrorEvent();
00151 
00153 
00158     static CEvent::Type getConnectedEvent();
00159 
00161 
00165     static CEvent::Type getDisconnectedEvent();
00166 
00168 
00173     static CEvent::Type getSwitchToScreenEvent();
00174 
00176 
00181     static CEvent::Type getSwitchInDirectionEvent();
00182 
00184 
00189     static CEvent::Type getKeyboardBroadcastEvent();
00190 
00192 
00197     static CEvent::Type getLockCursorToScreenEvent();
00198 
00200 
00201 private:
00202     // get canonical name of client
00203     CString             getName(const CBaseClientProxy*) const;
00204 
00205     // get the sides of the primary screen that have neighbors
00206     UInt32              getActivePrimarySides() const;
00207 
00208     // returns true iff mouse should be locked to the current screen
00209     // according to this object only, ignoring what the primary client
00210     // says.
00211     bool                isLockedToScreenServer() const;
00212 
00213     // returns true iff mouse should be locked to the current screen
00214     // according to this object or the primary client.
00215     bool                isLockedToScreen() const;
00216 
00217     // returns the jump zone of the client
00218     SInt32              getJumpZoneSize(CBaseClientProxy*) const;
00219 
00220     // change the active screen
00221     void                switchScreen(CBaseClientProxy*,
00222                             SInt32 x, SInt32 y, bool forScreenSaver);
00223 
00224     // jump to screen
00225     void                jumpToScreen(CBaseClientProxy*);
00226 
00227     // convert pixel position to fraction, using x or y depending on the
00228     // direction.
00229     float               mapToFraction(CBaseClientProxy*, EDirection,
00230                             SInt32 x, SInt32 y) const;
00231 
00232     // convert fraction to pixel position, writing only x or y depending
00233     // on the direction.
00234     void                mapToPixel(CBaseClientProxy*, EDirection, float f,
00235                             SInt32& x, SInt32& y) const;
00236 
00237     // returns true if the client has a neighbor anywhere along the edge
00238     // indicated by the direction.
00239     bool                hasAnyNeighbor(CBaseClientProxy*, EDirection) const;
00240 
00241     // lookup neighboring screen, mapping the coordinate independent of
00242     // the direction to the neighbor's coordinate space.
00243     CBaseClientProxy*   getNeighbor(CBaseClientProxy*, EDirection,
00244                             SInt32& x, SInt32& y) const;
00245 
00246     // lookup neighboring screen.  given a position relative to the
00247     // source screen, find the screen we should move onto and where.
00248     // if the position is sufficiently far from the source then we
00249     // cross multiple screens.  if there is no suitable screen then
00250     // return NULL and x,y are not modified.
00251     CBaseClientProxy*   mapToNeighbor(CBaseClientProxy*, EDirection,
00252                             SInt32& x, SInt32& y) const;
00253 
00254     // adjusts x and y or neither to avoid ending up in a jump zone
00255     // after entering the client in the given direction.
00256     void                avoidJumpZone(CBaseClientProxy*, EDirection,
00257                             SInt32& x, SInt32& y) const;
00258 
00259     // test if a switch is permitted.  this includes testing user
00260     // options like switch delay and tracking any state required to
00261     // implement them.  returns true iff a switch is permitted.
00262     bool                isSwitchOkay(CBaseClientProxy* dst, EDirection,
00263                             SInt32 x, SInt32 y, SInt32 xActive, SInt32 yActive);
00264 
00265     // update switch state due to a mouse move at \p x, \p y that
00266     // doesn't switch screens.
00267     void                noSwitch(SInt32 x, SInt32 y);
00268 
00269     // stop switch timers
00270     void                stopSwitch();
00271 
00272     // start two tap switch timer
00273     void                startSwitchTwoTap();
00274 
00275     // arm the two tap switch timer if \p x, \p y is outside the tap zone
00276     void                armSwitchTwoTap(SInt32 x, SInt32 y);
00277 
00278     // stop the two tap switch timer
00279     void                stopSwitchTwoTap();
00280 
00281     // returns true iff the two tap switch timer is started
00282     bool                isSwitchTwoTapStarted() const;
00283 
00284     // returns true iff should switch because of two tap
00285     bool                shouldSwitchTwoTap() const;
00286 
00287     // start delay switch timer
00288     void                startSwitchWait(SInt32 x, SInt32 y);
00289 
00290     // stop delay switch timer
00291     void                stopSwitchWait();
00292 
00293     // returns true iff the delay switch timer is started
00294     bool                isSwitchWaitStarted() const;
00295 
00296     // returns the corner (EScreenSwitchCornerMasks) where x,y is on the
00297     // given client.  corners have the given size.
00298     UInt32              getCorner(CBaseClientProxy*,
00299                             SInt32 x, SInt32 y, SInt32 size) const;
00300 
00301     // stop relative mouse moves
00302     void                stopRelativeMoves();
00303 
00304     // send screen options to \c client
00305     void                sendOptions(CBaseClientProxy* client) const;
00306 
00307     // process options from configuration
00308     void                processOptions();
00309 
00310     // event handlers
00311     void                handleShapeChanged(const CEvent&, void*);
00312     void                handleClipboardGrabbed(const CEvent&, void*);
00313     void                handleClipboardChanged(const CEvent&, void*);
00314     void                handleKeyDownEvent(const CEvent&, void*);
00315     void                handleKeyUpEvent(const CEvent&, void*);
00316     void                handleKeyRepeatEvent(const CEvent&, void*);
00317     void                handleButtonDownEvent(const CEvent&, void*);
00318     void                handleButtonUpEvent(const CEvent&, void*);
00319     void                handleMotionPrimaryEvent(const CEvent&, void*);
00320     void                handleMotionSecondaryEvent(const CEvent&, void*);
00321     void                handleWheelEvent(const CEvent&, void*);
00322     void                handleScreensaverActivatedEvent(const CEvent&, void*);
00323     void                handleScreensaverDeactivatedEvent(const CEvent&, void*);
00324     void                handleSwitchWaitTimeout(const CEvent&, void*);
00325     void                handleClientDisconnected(const CEvent&, void*);
00326     void                handleClientCloseTimeout(const CEvent&, void*);
00327     void                handleSwitchToScreenEvent(const CEvent&, void*);
00328     void                handleSwitchInDirectionEvent(const CEvent&, void*);
00329     void                handleKeyboardBroadcastEvent(const CEvent&,void*);
00330     void                handleLockCursorToScreenEvent(const CEvent&, void*);
00331     void                handleFakeInputBeginEvent(const CEvent&, void*);
00332     void                handleFakeInputEndEvent(const CEvent&, void*);
00333 
00334     // event processing
00335     void                onClipboardChanged(CBaseClientProxy* sender,
00336                             ClipboardID id, UInt32 seqNum);
00337     void                onScreensaver(bool activated);
00338     void                onKeyDown(KeyID, KeyModifierMask, KeyButton,
00339                             const char* screens);
00340     void                onKeyUp(KeyID, KeyModifierMask, KeyButton,
00341                             const char* screens);
00342     void                onKeyRepeat(KeyID, KeyModifierMask, SInt32, KeyButton);
00343     void                onMouseDown(ButtonID);
00344     void                onMouseUp(ButtonID);
00345     bool                onMouseMovePrimary(SInt32 x, SInt32 y);
00346     void                onMouseMoveSecondary(SInt32 dx, SInt32 dy);
00347     void                onMouseWheel(SInt32 xDelta, SInt32 yDelta);
00348 
00349     // add client to list and attach event handlers for client
00350     bool                addClient(CBaseClientProxy*);
00351 
00352     // remove client from list and detach event handlers for client
00353     bool                removeClient(CBaseClientProxy*);
00354 
00355     // close a client
00356     void                closeClient(CBaseClientProxy*, const char* msg);
00357 
00358     // close clients not in \p config
00359     void                closeClients(const CConfig& config);
00360 
00361     // close all clients whether they've completed the handshake or not,
00362     // except the primary client
00363     void                closeAllClients();
00364 
00365     // remove clients from internal state
00366     void                removeActiveClient(CBaseClientProxy*);
00367     void                removeOldClient(CBaseClientProxy*);
00368 
00369     // force the cursor off of \p client
00370     void                forceLeaveClient(CBaseClientProxy* client);
00371 
00372 private:
00373     class CClipboardInfo {
00374     public:
00375         CClipboardInfo();
00376 
00377     public:
00378         CClipboard      m_clipboard;
00379         CString         m_clipboardData;
00380         CString         m_clipboardOwner;
00381         UInt32          m_clipboardSeqNum;
00382     };
00383 
00384     // the primary screen client
00385     CPrimaryClient*     m_primaryClient;
00386 
00387     // all clients (including the primary client) indexed by name
00388     typedef std::map<CString, CBaseClientProxy*> CClientList;
00389     typedef std::set<CBaseClientProxy*> CClientSet;
00390     CClientList         m_clients;
00391     CClientSet          m_clientSet;
00392 
00393     // all old connections that we're waiting to hangup
00394     typedef std::map<CBaseClientProxy*, CEventQueueTimer*> COldClients;
00395     COldClients         m_oldClients;
00396 
00397     // the client with focus
00398     CBaseClientProxy*   m_active;
00399 
00400     // the sequence number of enter messages
00401     UInt32              m_seqNum;
00402 
00403     // current mouse position (in absolute screen coordinates) on
00404     // whichever screen is active
00405     SInt32              m_x, m_y;
00406 
00407     // last mouse deltas.  this is needed to smooth out double tap
00408     // on win32 which reports bogus mouse motion at the edge of
00409     // the screen when using low level hooks, synthesizing motion
00410     // in the opposite direction the mouse actually moved.
00411     SInt32              m_xDelta, m_yDelta;
00412     SInt32              m_xDelta2, m_yDelta2;
00413 
00414     // current configuration
00415     CConfig             m_config;
00416 
00417     // input filter (from m_config);
00418     CInputFilter*       m_inputFilter;
00419 
00420     // clipboard cache
00421     CClipboardInfo      m_clipboards[kClipboardEnd];
00422 
00423     // state saved when screen saver activates
00424     CBaseClientProxy*   m_activeSaver;
00425     SInt32              m_xSaver, m_ySaver;
00426 
00427     // common state for screen switch tests.  all tests are always
00428     // trying to reach the same screen in the same direction.
00429     EDirection          m_switchDir;
00430     CBaseClientProxy*   m_switchScreen;
00431 
00432     // state for delayed screen switching
00433     double              m_switchWaitDelay;
00434     CEventQueueTimer*   m_switchWaitTimer;
00435     SInt32              m_switchWaitX, m_switchWaitY;
00436 
00437     // state for double-tap screen switching
00438     double              m_switchTwoTapDelay;
00439     CStopwatch          m_switchTwoTapTimer;
00440     bool                m_switchTwoTapEngaged;
00441     bool                m_switchTwoTapArmed;
00442     SInt32              m_switchTwoTapZone;
00443 
00444     // relative mouse move option
00445     bool                m_relativeMoves;
00446 
00447     // flag whether or not we have broadcasting enabled and the screens to
00448     // which we should send broadcasted keys.
00449     bool                m_keyboardBroadcasting;
00450     CString             m_keyboardBroadcastingScreens;
00451 
00452     // screen locking (former scroll lock)
00453     bool                m_lockedToScreen;
00454 
00455     static CEvent::Type s_errorEvent;
00456     static CEvent::Type s_connectedEvent;
00457     static CEvent::Type s_disconnectedEvent;
00458     static CEvent::Type s_switchToScreen;
00459     static CEvent::Type s_switchInDirection;
00460     static CEvent::Type s_keyboardBroadcast;
00461     static CEvent::Type s_lockCursorToScreen;
00462 };
00463 
00464 #endif

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