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 | #ifndef CSERVER_H
|
---|
16 | #define CSERVER_H
|
---|
17 |
|
---|
18 | #include "CConfig.h"
|
---|
19 | #include "CClipboard.h"
|
---|
20 | #include "ClipboardTypes.h"
|
---|
21 | #include "KeyTypes.h"
|
---|
22 | #include "MouseTypes.h"
|
---|
23 | #include "CEvent.h"
|
---|
24 | #include "CStopwatch.h"
|
---|
25 | #include "stdmap.h"
|
---|
26 | #include "stdset.h"
|
---|
27 | #include "stdvector.h"
|
---|
28 |
|
---|
29 | class CBaseClientProxy;
|
---|
30 | class CEventQueueTimer;
|
---|
31 | class CPrimaryClient;
|
---|
32 | class CInputFilter;
|
---|
33 |
|
---|
34 | //! Synergy server
|
---|
35 | /*!
|
---|
36 | This class implements the top-level server algorithms for synergy.
|
---|
37 | */
|
---|
38 | class CServer {
|
---|
39 | public:
|
---|
40 | //! Lock cursor to screen data
|
---|
41 | class CLockCursorToScreenInfo {
|
---|
42 | public:
|
---|
43 | enum State { kOff, kOn, kToggle };
|
---|
44 |
|
---|
45 | static CLockCursorToScreenInfo* alloc(State state = kToggle);
|
---|
46 |
|
---|
47 | public:
|
---|
48 | State m_state;
|
---|
49 | };
|
---|
50 |
|
---|
51 | //! Switch to screen data
|
---|
52 | class CSwitchToScreenInfo {
|
---|
53 | public:
|
---|
54 | static CSwitchToScreenInfo* alloc(const CString& screen);
|
---|
55 |
|
---|
56 | public:
|
---|
57 | // this is a C-string; this type is a variable size structure
|
---|
58 | char m_screen[1];
|
---|
59 | };
|
---|
60 |
|
---|
61 | //! Switch in direction data
|
---|
62 | class CSwitchInDirectionInfo {
|
---|
63 | public:
|
---|
64 | static CSwitchInDirectionInfo* alloc(EDirection direction);
|
---|
65 |
|
---|
66 | public:
|
---|
67 | EDirection m_direction;
|
---|
68 | };
|
---|
69 |
|
---|
70 | //! Screen connected data
|
---|
71 | class CScreenConnectedInfo {
|
---|
72 | public:
|
---|
73 | static CScreenConnectedInfo* alloc(const CString& screen);
|
---|
74 |
|
---|
75 | public:
|
---|
76 | // this is a C-string; this type is a variable size structure
|
---|
77 | char m_screen[1];
|
---|
78 | };
|
---|
79 |
|
---|
80 | /*!
|
---|
81 | Start the server with the configuration \p config and the primary
|
---|
82 | client (local screen) \p primaryClient. The client retains
|
---|
83 | ownership of \p primaryClient.
|
---|
84 | */
|
---|
85 | CServer(const CConfig& config, CPrimaryClient* primaryClient);
|
---|
86 | ~CServer();
|
---|
87 |
|
---|
88 | //! @name manipulators
|
---|
89 | //@{
|
---|
90 |
|
---|
91 | //! Set configuration
|
---|
92 | /*!
|
---|
93 | Change the server's configuration. Returns true iff the new
|
---|
94 | configuration was accepted (it must include the server's name).
|
---|
95 | This will disconnect any clients no longer in the configuration.
|
---|
96 | */
|
---|
97 | bool setConfig(const CConfig&);
|
---|
98 |
|
---|
99 | //! Add a client
|
---|
100 | /*!
|
---|
101 | Adds \p client to the server. The client is adopted and will be
|
---|
102 | destroyed when the client disconnects or is disconnected.
|
---|
103 | */
|
---|
104 | void adoptClient(CBaseClientProxy* client);
|
---|
105 |
|
---|
106 | //! Disconnect clients
|
---|
107 | /*!
|
---|
108 | Disconnect clients. This tells them to disconnect but does not wait
|
---|
109 | for them to actually do so. The server sends the disconnected event
|
---|
110 | when they're all disconnected (or immediately if none are connected).
|
---|
111 | The caller can also just destroy this object to force the disconnection.
|
---|
112 | */
|
---|
113 | void disconnect();
|
---|
114 |
|
---|
115 | //@}
|
---|
116 | //! @name accessors
|
---|
117 | //@{
|
---|
118 |
|
---|
119 | //! Get number of connected clients
|
---|
120 | /*!
|
---|
121 | Returns the number of connected clients, including the server itself.
|
---|
122 | */
|
---|
123 | UInt32 getNumClients() const;
|
---|
124 |
|
---|
125 | //! Get the list of connected clients
|
---|
126 | /*!
|
---|
127 | Set the \c list to the names of the currently connected clients.
|
---|
128 | */
|
---|
129 | void getClients(std::vector<CString>& list) const;
|
---|
130 |
|
---|
131 | //! Get error event type
|
---|
132 | /*!
|
---|
133 | Returns the error event type. This is sent when the server fails
|
---|
134 | for some reason.
|
---|
135 | */
|
---|
136 | static CEvent::Type getErrorEvent();
|
---|
137 |
|
---|
138 | //! Get connected event type
|
---|
139 | /*!
|
---|
140 | Returns the connected event type. This is sent when a client screen
|
---|
141 | has connected. The event data is a \c CScreenConnectedInfo* that
|
---|
142 | indicates the connected screen.
|
---|
143 | */
|
---|
144 | static CEvent::Type getConnectedEvent();
|
---|
145 |
|
---|
146 | //! Get disconnected event type
|
---|
147 | /*!
|
---|
148 | Returns the disconnected event type. This is sent when all the
|
---|
149 | clients have disconnected.
|
---|
150 | */
|
---|
151 | static CEvent::Type getDisconnectedEvent();
|
---|
152 |
|
---|
153 | //! Get switch to screen event type
|
---|
154 | /*!
|
---|
155 | Returns the switch to screen event type. The server responds to this
|
---|
156 | by switching screens. The event data is a \c CSwitchToScreenInfo*
|
---|
157 | that indicates the target screen.
|
---|
158 | */
|
---|
159 | static CEvent::Type getSwitchToScreenEvent();
|
---|
160 |
|
---|
161 | //! Get switch in direction event type
|
---|
162 | /*!
|
---|
163 | Returns the switch in direction event type. The server responds to this
|
---|
164 | by switching screens. The event data is a \c CSwitchInDirectionInfo*
|
---|
165 | that indicates the target direction.
|
---|
166 | */
|
---|
167 | static CEvent::Type getSwitchInDirectionEvent();
|
---|
168 |
|
---|
169 | //! Get lock cursor event type
|
---|
170 | /*!
|
---|
171 | Returns the lock cursor event type. The server responds to this
|
---|
172 | by locking the cursor to the active screen or unlocking it. The
|
---|
173 | event data is a \c CLockCursorToScreenInfo*.
|
---|
174 | */
|
---|
175 | static CEvent::Type getLockCursorToScreenEvent();
|
---|
176 |
|
---|
177 | //@}
|
---|
178 |
|
---|
179 | private:
|
---|
180 | // get canonical name of client
|
---|
181 | CString getName(const CBaseClientProxy*) const;
|
---|
182 |
|
---|
183 | // get the sides of the primary screen that have neighbors
|
---|
184 | UInt32 getActivePrimarySides() const;
|
---|
185 |
|
---|
186 | // returns true iff mouse should be locked to the current screen
|
---|
187 | // according to this object only, ignoring what the primary client
|
---|
188 | // says.
|
---|
189 | bool isLockedToScreenServer() const;
|
---|
190 |
|
---|
191 | // returns true iff mouse should be locked to the current screen
|
---|
192 | // according to this object or the primary client.
|
---|
193 | bool isLockedToScreen() const;
|
---|
194 |
|
---|
195 | // returns the jump zone of the client
|
---|
196 | SInt32 getJumpZoneSize(CBaseClientProxy*) const;
|
---|
197 |
|
---|
198 | // change the active screen
|
---|
199 | void switchScreen(CBaseClientProxy*,
|
---|
200 | SInt32 x, SInt32 y, bool forScreenSaver);
|
---|
201 |
|
---|
202 | // jump to screen
|
---|
203 | void jumpToScreen(CBaseClientProxy*);
|
---|
204 |
|
---|
205 | // convert pixel position to fraction, using x or y depending on the
|
---|
206 | // direction.
|
---|
207 | float mapToFraction(CBaseClientProxy*, EDirection,
|
---|
208 | SInt32 x, SInt32 y) const;
|
---|
209 |
|
---|
210 | // convert fraction to pixel position, writing only x or y depending
|
---|
211 | // on the direction.
|
---|
212 | void mapToPixel(CBaseClientProxy*, EDirection, float f,
|
---|
213 | SInt32& x, SInt32& y) const;
|
---|
214 |
|
---|
215 | // returns true if the client has a neighbor anywhere along the edge
|
---|
216 | // indicated by the direction.
|
---|
217 | bool hasAnyNeighbor(CBaseClientProxy*, EDirection) const;
|
---|
218 |
|
---|
219 | // lookup neighboring screen, mapping the coordinate independent of
|
---|
220 | // the direction to the neighbor's coordinate space.
|
---|
221 | CBaseClientProxy* getNeighbor(CBaseClientProxy*, EDirection,
|
---|
222 | SInt32& x, SInt32& y) const;
|
---|
223 |
|
---|
224 | // lookup neighboring screen. given a position relative to the
|
---|
225 | // source screen, find the screen we should move onto and where.
|
---|
226 | // if the position is sufficiently far from the source then we
|
---|
227 | // cross multiple screens. if there is no suitable screen then
|
---|
228 | // return NULL and x,y are not modified.
|
---|
229 | CBaseClientProxy* mapToNeighbor(CBaseClientProxy*, EDirection,
|
---|
230 | SInt32& x, SInt32& y) const;
|
---|
231 |
|
---|
232 | // adjusts x and y or neither to avoid ending up in a jump zone
|
---|
233 | // after entering the client in the given direction.
|
---|
234 | void avoidJumpZone(CBaseClientProxy*, EDirection,
|
---|
235 | SInt32& x, SInt32& y) const;
|
---|
236 |
|
---|
237 | // test if a switch is permitted. this includes testing user
|
---|
238 | // options like switch delay and tracking any state required to
|
---|
239 | // implement them. returns true iff a switch is permitted.
|
---|
240 | bool isSwitchOkay(CBaseClientProxy* dst, EDirection,
|
---|
241 | SInt32 x, SInt32 y, SInt32 xActive, SInt32 yActive);
|
---|
242 |
|
---|
243 | // update switch state due to a mouse move at \p x, \p y that
|
---|
244 | // doesn't switch screens.
|
---|
245 | void noSwitch(SInt32 x, SInt32 y);
|
---|
246 |
|
---|
247 | // stop switch timers
|
---|
248 | void stopSwitch();
|
---|
249 |
|
---|
250 | // start two tap switch timer
|
---|
251 | void startSwitchTwoTap();
|
---|
252 |
|
---|
253 | // arm the two tap switch timer if \p x, \p y is outside the tap zone
|
---|
254 | void armSwitchTwoTap(SInt32 x, SInt32 y);
|
---|
255 |
|
---|
256 | // stop the two tap switch timer
|
---|
257 | void stopSwitchTwoTap();
|
---|
258 |
|
---|
259 | // returns true iff the two tap switch timer is started
|
---|
260 | bool isSwitchTwoTapStarted() const;
|
---|
261 |
|
---|
262 | // returns true iff should switch because of two tap
|
---|
263 | bool shouldSwitchTwoTap() const;
|
---|
264 |
|
---|
265 | // start delay switch timer
|
---|
266 | void startSwitchWait(SInt32 x, SInt32 y);
|
---|
267 |
|
---|
268 | // stop delay switch timer
|
---|
269 | void stopSwitchWait();
|
---|
270 |
|
---|
271 | // returns true iff the delay switch timer is started
|
---|
272 | bool isSwitchWaitStarted() const;
|
---|
273 |
|
---|
274 | // returns the corner (EScreenSwitchCornerMasks) where x,y is on the
|
---|
275 | // given client. corners have the given size.
|
---|
276 | UInt32 getCorner(CBaseClientProxy*,
|
---|
277 | SInt32 x, SInt32 y, SInt32 size) const;
|
---|
278 |
|
---|
279 | // stop relative mouse moves
|
---|
280 | void stopRelativeMoves();
|
---|
281 |
|
---|
282 | // send screen options to \c client
|
---|
283 | void sendOptions(CBaseClientProxy* client) const;
|
---|
284 |
|
---|
285 | // process options from configuration
|
---|
286 | void processOptions();
|
---|
287 |
|
---|
288 | // event handlers
|
---|
289 | void handleShapeChanged(const CEvent&, void*);
|
---|
290 | void handleClipboardGrabbed(const CEvent&, void*);
|
---|
291 | void handleClipboardChanged(const CEvent&, void*);
|
---|
292 | void handleKeyDownEvent(const CEvent&, void*);
|
---|
293 | void handleKeyUpEvent(const CEvent&, void*);
|
---|
294 | void handleKeyRepeatEvent(const CEvent&, void*);
|
---|
295 | void handleButtonDownEvent(const CEvent&, void*);
|
---|
296 | void handleButtonUpEvent(const CEvent&, void*);
|
---|
297 | void handleMotionPrimaryEvent(const CEvent&, void*);
|
---|
298 | void handleMotionSecondaryEvent(const CEvent&, void*);
|
---|
299 | void handleWheelEvent(const CEvent&, void*);
|
---|
300 | void handleScreensaverActivatedEvent(const CEvent&, void*);
|
---|
301 | void handleScreensaverDeactivatedEvent(const CEvent&, void*);
|
---|
302 | void handleSwitchWaitTimeout(const CEvent&, void*);
|
---|
303 | void handleClientDisconnected(const CEvent&, void*);
|
---|
304 | void handleClientCloseTimeout(const CEvent&, void*);
|
---|
305 | void handleSwitchToScreenEvent(const CEvent&, void*);
|
---|
306 | void handleSwitchInDirectionEvent(const CEvent&, void*);
|
---|
307 | void handleLockCursorToScreenEvent(const CEvent&, void*);
|
---|
308 | void handleFakeInputBeginEvent(const CEvent&, void*);
|
---|
309 | void handleFakeInputEndEvent(const CEvent&, void*);
|
---|
310 |
|
---|
311 | // event processing
|
---|
312 | void onClipboardChanged(CBaseClientProxy* sender,
|
---|
313 | ClipboardID id, UInt32 seqNum);
|
---|
314 | void onScreensaver(bool activated);
|
---|
315 | void onKeyDown(KeyID, KeyModifierMask, KeyButton,
|
---|
316 | const char* screens);
|
---|
317 | void onKeyUp(KeyID, KeyModifierMask, KeyButton,
|
---|
318 | const char* screens);
|
---|
319 | void onKeyRepeat(KeyID, KeyModifierMask, SInt32, KeyButton);
|
---|
320 | void onMouseDown(ButtonID);
|
---|
321 | void onMouseUp(ButtonID);
|
---|
322 | bool onMouseMovePrimary(SInt32 x, SInt32 y);
|
---|
323 | void onMouseMoveSecondary(SInt32 dx, SInt32 dy);
|
---|
324 | void onMouseWheel(SInt32 xDelta, SInt32 yDelta);
|
---|
325 |
|
---|
326 | // add client to list and attach event handlers for client
|
---|
327 | bool addClient(CBaseClientProxy*);
|
---|
328 |
|
---|
329 | // remove client from list and detach event handlers for client
|
---|
330 | bool removeClient(CBaseClientProxy*);
|
---|
331 |
|
---|
332 | // close a client
|
---|
333 | void closeClient(CBaseClientProxy*, const char* msg);
|
---|
334 |
|
---|
335 | // close clients not in \p config
|
---|
336 | void closeClients(const CConfig& config);
|
---|
337 |
|
---|
338 | // close all clients whether they've completed the handshake or not,
|
---|
339 | // except the primary client
|
---|
340 | void closeAllClients();
|
---|
341 |
|
---|
342 | // remove clients from internal state
|
---|
343 | void removeActiveClient(CBaseClientProxy*);
|
---|
344 | void removeOldClient(CBaseClientProxy*);
|
---|
345 |
|
---|
346 | // force the cursor off of \p client
|
---|
347 | void forceLeaveClient(CBaseClientProxy* client);
|
---|
348 |
|
---|
349 | private:
|
---|
350 | class CClipboardInfo {
|
---|
351 | public:
|
---|
352 | CClipboardInfo();
|
---|
353 |
|
---|
354 | public:
|
---|
355 | CClipboard m_clipboard;
|
---|
356 | CString m_clipboardData;
|
---|
357 | CString m_clipboardOwner;
|
---|
358 | UInt32 m_clipboardSeqNum;
|
---|
359 | };
|
---|
360 |
|
---|
361 | // the primary screen client
|
---|
362 | CPrimaryClient* m_primaryClient;
|
---|
363 |
|
---|
364 | // all clients (including the primary client) indexed by name
|
---|
365 | typedef std::map<CString, CBaseClientProxy*> CClientList;
|
---|
366 | typedef std::set<CBaseClientProxy*> CClientSet;
|
---|
367 | CClientList m_clients;
|
---|
368 | CClientSet m_clientSet;
|
---|
369 |
|
---|
370 | // all old connections that we're waiting to hangup
|
---|
371 | typedef std::map<CBaseClientProxy*, CEventQueueTimer*> COldClients;
|
---|
372 | COldClients m_oldClients;
|
---|
373 |
|
---|
374 | // the client with focus
|
---|
375 | CBaseClientProxy* m_active;
|
---|
376 |
|
---|
377 | // the sequence number of enter messages
|
---|
378 | UInt32 m_seqNum;
|
---|
379 |
|
---|
380 | // current mouse position (in absolute screen coordinates) on
|
---|
381 | // whichever screen is active
|
---|
382 | SInt32 m_x, m_y;
|
---|
383 |
|
---|
384 | // last mouse deltas. this is needed to smooth out double tap
|
---|
385 | // on win32 which reports bogus mouse motion at the edge of
|
---|
386 | // the screen when using low level hooks, synthesizing motion
|
---|
387 | // in the opposite direction the mouse actually moved.
|
---|
388 | SInt32 m_xDelta, m_yDelta;
|
---|
389 | SInt32 m_xDelta2, m_yDelta2;
|
---|
390 |
|
---|
391 | // current configuration
|
---|
392 | CConfig m_config;
|
---|
393 |
|
---|
394 | // input filter (from m_config);
|
---|
395 | CInputFilter* m_inputFilter;
|
---|
396 |
|
---|
397 | // clipboard cache
|
---|
398 | CClipboardInfo m_clipboards[kClipboardEnd];
|
---|
399 |
|
---|
400 | // state saved when screen saver activates
|
---|
401 | CBaseClientProxy* m_activeSaver;
|
---|
402 | SInt32 m_xSaver, m_ySaver;
|
---|
403 |
|
---|
404 | // common state for screen switch tests. all tests are always
|
---|
405 | // trying to reach the same screen in the same direction.
|
---|
406 | EDirection m_switchDir;
|
---|
407 | CBaseClientProxy* m_switchScreen;
|
---|
408 |
|
---|
409 | // state for delayed screen switching
|
---|
410 | double m_switchWaitDelay;
|
---|
411 | CEventQueueTimer* m_switchWaitTimer;
|
---|
412 | SInt32 m_switchWaitX, m_switchWaitY;
|
---|
413 |
|
---|
414 | // state for double-tap screen switching
|
---|
415 | double m_switchTwoTapDelay;
|
---|
416 | CStopwatch m_switchTwoTapTimer;
|
---|
417 | bool m_switchTwoTapEngaged;
|
---|
418 | bool m_switchTwoTapArmed;
|
---|
419 | SInt32 m_switchTwoTapZone;
|
---|
420 |
|
---|
421 | // relative mouse move option
|
---|
422 | bool m_relativeMoves;
|
---|
423 |
|
---|
424 | // screen locking (former scroll lock)
|
---|
425 | bool m_lockedToScreen;
|
---|
426 |
|
---|
427 | static CEvent::Type s_errorEvent;
|
---|
428 | static CEvent::Type s_connectedEvent;
|
---|
429 | static CEvent::Type s_disconnectedEvent;
|
---|
430 | static CEvent::Type s_switchToScreen;
|
---|
431 | static CEvent::Type s_switchInDirection;
|
---|
432 | static CEvent::Type s_lockCursorToScreen;
|
---|
433 | };
|
---|
434 |
|
---|
435 | #endif
|
---|