Deskflow 1.26.0.314
Keyboard and mouse sharing utility
Loading...
Searching...
No Matches
Server.h
Go to the documentation of this file.
1/*
2 * Deskflow -- mouse and keyboard sharing utility
3 * SPDX-FileCopyrightText: (C) 2025 Deskflow Developers
4 * SPDX-FileCopyrightText: (C) 2012 Synergy App Ltd
5 * SPDX-FileCopyrightText: (C) 2002 Chris Schoeneman
6 * SPDX-License-Identifier: GPL-2.0-only WITH LicenseRef-OpenSSL-Exception
7 */
8
9#pragma once
10
11#include "base/Event.h"
12#include "base/Stopwatch.h"
14#include "deskflow/Clipboard.h"
16#include "deskflow/KeyTypes.h"
17#include "deskflow/MouseTypes.h"
18#include "server/Config.h"
19
20#include <climits>
21#include <map>
22#include <set>
23#include <vector>
24
25class BaseClientProxy;
26class EventQueueTimer;
27class PrimaryClient;
28class InputFilter;
29namespace deskflow {
30class Screen;
31}
32class IEventQueue;
33class Thread;
34class ClientListener;
35
37
40class Server
41{
42 using ServerConfig = deskflow::server::Config;
43
44public:
47 {
48 public:
49 enum State
50 {
54 };
55
56 explicit LockCursorToScreenInfo(State state = kToggle) : m_state(state)
57 {
58 // do nothing
59 }
60 ~LockCursorToScreenInfo() override = default; // do nothing
61
62 public:
64 };
65
68 {
69 public:
70 explicit SwitchToScreenInfo(const std::string &screen) : m_screen(screen)
71 {
72 // do nothing
73 }
74 ~SwitchToScreenInfo() override = default; // do nothing
75
76 public:
77 std::string m_screen;
78 };
79
82 {
83 public:
84 explicit SwitchInDirectionInfo(Direction direction) : m_direction(direction)
85 {
86 // do nothing
87 }
88 ~SwitchInDirectionInfo() override = default; // do nothing
89
90 public:
92 };
93
96 {
97 public:
98 explicit ScreenConnectedInfo(std::string screen) : m_screen(screen)
99 {
100 // do nothing
101 }
102
103 public:
104 std::string m_screen; // was char[1]
105 };
106
109 {
110 public:
111 enum State
112 {
116 };
117
118 explicit KeyboardBroadcastInfo(State state = kToggle) : m_state(state)
119 {
120 // do nothing
121 }
122 KeyboardBroadcastInfo(State state, const std::string &screens) : m_state(state), m_screens(screens)
123 {
124 // do nothing
125 }
126 ~KeyboardBroadcastInfo() override = default; // do nothing
127
128 public:
130 std::string m_screens;
131 };
132
138 Server(ServerConfig &config, PrimaryClient *primaryClient, deskflow::Screen *screen, IEventQueue *events);
139 Server(Server const &) = delete;
140 Server(Server &&) = delete;
141 ~Server();
142
143 Server &operator=(Server const &) = delete;
144 Server &operator=(Server &&) = delete;
145
147
148
150
155 bool setConfig(const ServerConfig &);
156
158
162 void adoptClient(BaseClientProxy *client);
163
165
171 void disconnect();
172
175 {
176 m_clientListener = p;
177 }
178
180
182
184
187 std::string protocolString() const;
188
190
193 uint32_t getNumClients() const;
194
196
199 void getClients(std::vector<std::string> &list) const;
200 void sendConnectedClientsIpc() const;
201 size_t getMaximumClipboardSizeBytes() const;
202
204
205private:
206 // get canonical name of client
207 std::string getName(const BaseClientProxy *) const;
208
209 // get the sides of the primary screen that have neighbors
210 uint32_t getActivePrimarySides() const;
211
212 // returns true iff mouse should be locked to the current screen
213 // according to this object only, ignoring what the primary client
214 // says.
215 bool isLockedToScreenServer() const;
216
217 // returns true iff mouse should be locked to the current screen
218 // according to this object or the primary client.
219 bool isLockedToScreen() const;
220
221 // returns the jump zone of the client
222 int32_t getJumpZoneSize(const BaseClientProxy *) const;
223
224 // change the active screen
225 void switchScreen(BaseClientProxy *, int32_t x, int32_t y, bool forScreenSaver);
226
227 // jump to screen
228 void jumpToScreen(BaseClientProxy *);
229
230 // convert pixel position to fraction, using x or y depending on the
231 // direction.
232 float mapToFraction(const BaseClientProxy *, Direction, int32_t x, int32_t y) const;
233
234 // convert fraction to pixel position, writing only x or y depending
235 // on the direction.
236 void mapToPixel(const BaseClientProxy *, Direction, float f, int32_t &x, int32_t &y) const;
237
238 // returns true if the client has a neighbor anywhere along the edge
239 // indicated by the direction.
240 bool hasAnyNeighbor(const BaseClientProxy *, Direction) const;
241
242 // lookup neighboring screen, mapping the coordinate independent of
243 // the direction to the neighbor's coordinate space.
244 BaseClientProxy *getNeighbor(const BaseClientProxy *, Direction, int32_t &x, int32_t &y) const;
245
246 // lookup neighboring screen. given a position relative to the
247 // source screen, find the screen we should move onto and where.
248 // if the position is sufficiently far from the source then we
249 // cross multiple screens. if there is no suitable screen then
250 // return nullptr and x,y are not modified.
251 BaseClientProxy *mapToNeighbor(BaseClientProxy *, Direction, int32_t &x, int32_t &y) const;
252
253 // adjusts x and y or neither to avoid ending up in a jump zone
254 // after entering the client in the given direction.
255 void avoidJumpZone(const BaseClientProxy *, Direction, int32_t &x, int32_t &y) const;
256
257 // test if a switch is permitted. this includes testing user
258 // options like switch delay and tracking any state required to
259 // implement them. returns true iff a switch is permitted.
260 bool isSwitchOkay(BaseClientProxy *dst, Direction, int32_t x, int32_t y, int32_t xActive, int32_t yActive);
261
262 // update switch state due to a mouse move at \p x, \p y that
263 // doesn't switch screens.
264 void noSwitch(int32_t x, int32_t y);
265
266 // stop switch timers
267 void stopSwitch();
268
269 // start two tap switch timer
270 void startSwitchTwoTap();
271
272 // arm the two tap switch timer if \p x, \p y is outside the tap zone
273 void armSwitchTwoTap(int32_t x, int32_t y);
274
275 // stop the two tap switch timer
276 void stopSwitchTwoTap();
277
278 // returns true iff the two tap switch timer is started
279 bool isSwitchTwoTapStarted() const;
280
281 // returns true iff should switch because of two tap
282 bool shouldSwitchTwoTap() const;
283
284 // start delay switch timer
285 void startSwitchWait(int32_t x, int32_t y);
286
287 // stop delay switch timer
288 void stopSwitchWait();
289
290 // returns true iff the delay switch timer is started
291 bool isSwitchWaitStarted() const;
292
293 // returns the corner (EScreenSwitchCornerMasks) where x,y is on the
294 // given client. corners have the given size.
295 uint32_t getCorner(const BaseClientProxy *, int32_t x, int32_t y, int32_t size) const;
296
297 // stop relative mouse moves
298 void stopRelativeMoves();
299
300 // send screen options to \c client
301 void sendOptions(BaseClientProxy *client) const;
302
303 // process options from configuration
304 void processOptions();
305
306 // event handlers
307 void handleShapeChanged(BaseClientProxy *client);
308 void handleClipboardGrabbed(const Event &event, BaseClientProxy *client);
309 void handleClipboardChanged(const Event &event, BaseClientProxy *client);
310 void handleKeyDownEvent(const Event &event);
311 void handleKeyUpEvent(const Event &event);
312 void handleKeyRepeatEvent(const Event &event);
313 void handleButtonDownEvent(const Event &event);
314 void handleButtonUpEvent(const Event &event);
315 void handleMotionPrimaryEvent(const Event &event);
316 void handleMotionSecondaryEvent(const Event &event);
317 void handleWheelEvent(const Event &event);
318 void handleSwitchWaitTimeout();
319 void handleClientDisconnected(BaseClientProxy *client);
320 void handleClientCloseTimeout(BaseClientProxy *client);
321 void handleSwitchToScreenEvent(const Event &event);
322 void handleSwitchInDirectionEvent(const Event &event);
323 void handleToggleScreenEvent(const Event &);
324 void handleKeyboardBroadcastEvent(const Event &event);
325 void handleLockCursorToScreenEvent(const Event &event);
326
327 // event processing
328 void onClipboardChanged(const BaseClientProxy *sender, ClipboardID id, uint32_t seqNum);
329 void onScreensaver(bool activated);
330 void onKeyDown(KeyID, KeyModifierMask, KeyButton, const std::string &, const char *screens);
331 void onKeyUp(KeyID, KeyModifierMask, KeyButton, const char *screens);
332 void onKeyRepeat(KeyID, KeyModifierMask, int32_t, KeyButton, const std::string &);
333 void onMouseDown(ButtonID);
334 void onMouseUp(ButtonID);
335 bool onMouseMovePrimary(int32_t x, int32_t y);
336 void onMouseMoveSecondary(int32_t dx, int32_t dy);
337 void onMouseWheel(int32_t xDelta, int32_t yDelta);
338
339 // add client to list and attach event handlers for client
340 bool addClient(BaseClientProxy *);
341
342 // remove client from list and detach event handlers for client
343 bool removeClient(BaseClientProxy *);
344
345 // close a client
346 void closeClient(BaseClientProxy *, const char *msg);
347
348 // close clients not in \p config
349 void closeClients(const ServerConfig &config);
350
351 // close all clients whether they've completed the handshake or not,
352 // except the primary client
353 void closeAllClients();
354
355 // remove clients from internal state
356 void removeActiveClient(BaseClientProxy *);
357 void removeOldClient(BaseClientProxy *);
358
359 // force the cursor off of \p client
360 void forceLeaveClient(const BaseClientProxy *client);
361
362private:
363 class ClipboardInfo
364 {
365 public:
366 ClipboardInfo() = default;
367
368 public:
369 Clipboard m_clipboard;
370 std::string m_clipboardData;
371 std::string m_clipboardOwner;
372 uint32_t m_clipboardSeqNum = 0;
373 };
374 // Order suggested by clang
375
376 // the Primary Screen Client
377 PrimaryClient *m_primaryClient = nullptr;
378
379 // the client with focus
380 BaseClientProxy *m_active = nullptr;
381
382 // current configuration
383 ServerConfig *m_config = nullptr;
384
385 // input filter (from m_config);
386 InputFilter *m_inputFilter = nullptr;
387
388 // state saved when screen saver activates
389 BaseClientProxy *m_activeSaver = nullptr;
390
391 BaseClientProxy *m_switchScreen = nullptr;
392 double m_switchWaitDelay = 0.0;
393 EventQueueTimer *m_switchWaitTimer = nullptr;
394
395 // delay for double-tap screen switching
396 double m_switchTwoTapDelay = 0.0;
397
398 // server screen
399 deskflow::Screen *m_screen;
400
401 IEventQueue *m_events = nullptr;
402 size_t m_maximumClipboardSize = INT_MAX;
403 ClientListener *m_clientListener = nullptr;
404 Stopwatch m_switchTwoTapTimer;
405
406 // Name of screen broadcasting the keyboard events
407 std::string m_keyboardBroadcastingScreens;
408
409 // all clients (including the primary client) indexed by name
410 using ClientList = std::map<std::string, BaseClientProxy *>;
411 using ClientSet = std::set<BaseClientProxy *>;
412 ClientList m_clients;
413 ClientSet m_clientSet;
414
415 // all old connections that we're waiting to hangup
416 using OldClients = std::map<BaseClientProxy *, EventQueueTimer *>;
417 OldClients m_oldClients;
418
419 // clipboard cache
420 ClipboardInfo m_clipboards[kClipboardEnd];
421
422 // used in hello message sent to the client
424
425 // the sequence number of enter messages
426 uint32_t m_seqNum = 0;
427
428 // current mouse position (in absolute screen coordinates) on
429 // whichever screen is active
430 int32_t m_x;
431 int32_t m_y;
432
433 // last mouse deltas. this is needed to smooth out double tap
434 // on win32 which reports bogus mouse motion at the edge of
435 // the screen when using low level hooks, synthesizing motion
436 // in the opposite direction the mouse actually moved.
437 int32_t m_xDelta = 0;
438 int32_t m_yDelta = 0;
439 int32_t m_xDelta2 = 0;
440 int32_t m_yDelta2 = 0;
441
442 int32_t m_xSaver;
443 int32_t m_ySaver;
444
445 // state for delayed screen switching
446 int32_t m_switchWaitX;
447 int32_t m_switchWaitY;
448
449 int32_t m_switchTwoTapZone = 3;
450
451 // common state for screen switch tests. all tests are always
452 // trying to reach the same screen in the same direction.
453 Direction m_switchDir = Direction::NoDirection;
454
455 bool m_switchTwoTapEngaged = false;
456 bool m_switchTwoTapArmed = false;
457
458 // relative mouse move option
459 bool m_relativeMoves = false;
460
461 // flag whether or not we have broadcasting enabled and the screens to
462 // which we should send broadcasted keys.
463 bool m_keyboardBroadcasting = false;
464
465 // screen locking (former scroll lock)
466 bool m_lockedToScreen = false;
467
468 bool m_defaultLockToScreenState = false;
469 bool m_disableLockToScreen = false;
470 bool m_enableClipboard = true;
471};
static const ClipboardID kClipboardEnd
Definition ClipboardTypes.h:30
uint8_t ClipboardID
Clipboard ID.
Definition ClipboardTypes.h:16
Direction
Computer edge directions for mouse movement.
Definition DirectionTypes.h:22
@ NoDirection
No specific direction.
Definition DirectionTypes.h:23
uint32_t KeyID
Key ID.
Definition KeyTypes.h:21
uint16_t KeyButton
Key Code.
Definition KeyTypes.h:34
uint32_t KeyModifierMask
Modifier key mask.
Definition KeyTypes.h:44
uint8_t ButtonID
Mouse button ID.
Definition MouseTypes.h:16
NetworkProtocol
Definition NetworkProtocol.h:15
@ Barrier
Definition NetworkProtocol.h:18
int y
Definition ServerConfig.cpp:24
int x
Definition ServerConfig.cpp:23
Generic proxy for client or primary.
Definition BaseClientProxy.h:18
Definition ClientListener.h:28
Memory buffer clipboard.
Definition Clipboard.h:19
EventData()=default
Definition EventQueueTimer.h:12
Event.
Definition Event.h:43
Event queue interface.
Definition IEventQueue.h:29
Definition InputFilter.h:23
Primary screen as pseudo-client.
Definition PrimaryClient.h:23
Definition ServerConfig.h:25
State m_state
Definition Server.h:129
~KeyboardBroadcastInfo() override=default
KeyboardBroadcastInfo(State state, const std::string &screens)
Definition Server.h:122
KeyboardBroadcastInfo(State state=kToggle)
Definition Server.h:118
std::string m_screens
Definition Server.h:130
State
Definition Server.h:112
@ kOff
Definition Server.h:113
@ kOn
Definition Server.h:114
@ kToggle
Definition Server.h:115
State
Definition Server.h:50
@ kOn
Definition Server.h:52
@ kToggle
Definition Server.h:53
@ kOff
Definition Server.h:51
LockCursorToScreenInfo(State state=kToggle)
Definition Server.h:56
~LockCursorToScreenInfo() override=default
State m_state
Definition Server.h:63
std::string m_screen
Definition Server.h:104
ScreenConnectedInfo(std::string screen)
Definition Server.h:98
SwitchInDirectionInfo(Direction direction)
Definition Server.h:84
Direction m_direction
Definition Server.h:91
~SwitchInDirectionInfo() override=default
SwitchToScreenInfo(const std::string &screen)
Definition Server.h:70
std::string m_screen
Definition Server.h:77
~SwitchToScreenInfo() override=default
void sendConnectedClientsIpc() const
Definition Server.cpp:303
Server & operator=(Server const &)=delete
size_t getMaximumClipboardSizeBytes() const
Definition Server.cpp:186
Server(ServerConfig &config, PrimaryClient *primaryClient, deskflow::Screen *screen, IEventQueue *events)
Definition Server.cpp:43
Server & operator=(Server &&)=delete
~Server()
Definition Server.cpp:144
void adoptClient(BaseClientProxy *client)
Add a client.
Definition Server.cpp:231
Server(Server &&)=delete
std::string protocolString() const
Get the network protocol.
Definition Server.cpp:283
bool setConfig(const ServerConfig &)
Set configuration.
Definition Server.cpp:191
void getClients(std::vector< std::string > &list) const
Get the list of connected clients.
Definition Server.cpp:295
void setListener(ClientListener *p)
Store ClientListener pointer.
Definition Server.h:174
uint32_t getNumClients() const
Get number of connected clients.
Definition Server.cpp:290
Server(Server const &)=delete
void disconnect()
Disconnect clients.
Definition Server.cpp:272
Thread handle.
Definition Thread.h:33
Platform independent screen.
Definition Screen.h:30
Server configuration.
Definition Config.h:53
Definition DaemonApp.h:18