Deskflow 1.26.0.0
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 Symless 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"
13#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
202
203private:
204 // get canonical name of client
205 std::string getName(const BaseClientProxy *) const;
206
207 // get the sides of the primary screen that have neighbors
208 uint32_t getActivePrimarySides() const;
209
210 // returns true iff mouse should be locked to the current screen
211 // according to this object only, ignoring what the primary client
212 // says.
213 bool isLockedToScreenServer() const;
214
215 // returns true iff mouse should be locked to the current screen
216 // according to this object or the primary client.
217 bool isLockedToScreen() const;
218
219 // returns the jump zone of the client
220 int32_t getJumpZoneSize(const BaseClientProxy *) const;
221
222 // change the active screen
223 void switchScreen(BaseClientProxy *, int32_t x, int32_t y, bool forScreenSaver);
224
225 // jump to screen
226 void jumpToScreen(BaseClientProxy *);
227
228 // convert pixel position to fraction, using x or y depending on the
229 // direction.
230 float mapToFraction(const BaseClientProxy *, Direction, int32_t x, int32_t y) const;
231
232 // convert fraction to pixel position, writing only x or y depending
233 // on the direction.
234 void mapToPixel(const BaseClientProxy *, Direction, float f, int32_t &x, int32_t &y) const;
235
236 // returns true if the client has a neighbor anywhere along the edge
237 // indicated by the direction.
238 bool hasAnyNeighbor(const BaseClientProxy *, Direction) const;
239
240 // lookup neighboring screen, mapping the coordinate independent of
241 // the direction to the neighbor's coordinate space.
242 BaseClientProxy *getNeighbor(const BaseClientProxy *, Direction, int32_t &x, int32_t &y) const;
243
244 // lookup neighboring screen. given a position relative to the
245 // source screen, find the screen we should move onto and where.
246 // if the position is sufficiently far from the source then we
247 // cross multiple screens. if there is no suitable screen then
248 // return nullptr and x,y are not modified.
249 BaseClientProxy *mapToNeighbor(BaseClientProxy *, Direction, int32_t &x, int32_t &y) const;
250
251 // adjusts x and y or neither to avoid ending up in a jump zone
252 // after entering the client in the given direction.
253 void avoidJumpZone(const BaseClientProxy *, Direction, int32_t &x, int32_t &y) const;
254
255 // test if a switch is permitted. this includes testing user
256 // options like switch delay and tracking any state required to
257 // implement them. returns true iff a switch is permitted.
258 bool isSwitchOkay(BaseClientProxy *dst, Direction, int32_t x, int32_t y, int32_t xActive, int32_t yActive);
259
260 // update switch state due to a mouse move at \p x, \p y that
261 // doesn't switch screens.
262 void noSwitch(int32_t x, int32_t y);
263
264 // stop switch timers
265 void stopSwitch();
266
267 // start two tap switch timer
268 void startSwitchTwoTap();
269
270 // arm the two tap switch timer if \p x, \p y is outside the tap zone
271 void armSwitchTwoTap(int32_t x, int32_t y);
272
273 // stop the two tap switch timer
274 void stopSwitchTwoTap();
275
276 // returns true iff the two tap switch timer is started
277 bool isSwitchTwoTapStarted() const;
278
279 // returns true iff should switch because of two tap
280 bool shouldSwitchTwoTap() const;
281
282 // start delay switch timer
283 void startSwitchWait(int32_t x, int32_t y);
284
285 // stop delay switch timer
286 void stopSwitchWait();
287
288 // returns true iff the delay switch timer is started
289 bool isSwitchWaitStarted() const;
290
291 // returns the corner (EScreenSwitchCornerMasks) where x,y is on the
292 // given client. corners have the given size.
293 uint32_t getCorner(const BaseClientProxy *, int32_t x, int32_t y, int32_t size) const;
294
295 // stop relative mouse moves
296 void stopRelativeMoves();
297
298 // send screen options to \c client
299 void sendOptions(BaseClientProxy *client) const;
300
301 // process options from configuration
302 void processOptions();
303
304 // event handlers
305 void handleShapeChanged(BaseClientProxy *client);
306 void handleClipboardGrabbed(const Event &event, BaseClientProxy *client);
307 void handleClipboardChanged(const Event &event, BaseClientProxy *client);
308 void handleKeyDownEvent(const Event &event);
309 void handleKeyUpEvent(const Event &event);
310 void handleKeyRepeatEvent(const Event &event);
311 void handleButtonDownEvent(const Event &event);
312 void handleButtonUpEvent(const Event &event);
313 void handleMotionPrimaryEvent(const Event &event);
314 void handleMotionSecondaryEvent(const Event &event);
315 void handleWheelEvent(const Event &event);
316 void handleSwitchWaitTimeout();
317 void handleClientDisconnected(BaseClientProxy *client);
318 void handleClientCloseTimeout(BaseClientProxy *client);
319 void handleSwitchToScreenEvent(const Event &event);
320 void handleSwitchInDirectionEvent(const Event &event);
321 void handleToggleScreenEvent(const Event &);
322 void handleKeyboardBroadcastEvent(const Event &event);
323 void handleLockCursorToScreenEvent(const Event &event);
324
325 // event processing
326 void onClipboardChanged(const BaseClientProxy *sender, ClipboardID id, uint32_t seqNum);
327 void onScreensaver(bool activated);
328 void onKeyDown(KeyID, KeyModifierMask, KeyButton, const std::string &, const char *screens);
329 void onKeyUp(KeyID, KeyModifierMask, KeyButton, const char *screens);
330 void onKeyRepeat(KeyID, KeyModifierMask, int32_t, KeyButton, const std::string &);
331 void onMouseDown(ButtonID);
332 void onMouseUp(ButtonID);
333 bool onMouseMovePrimary(int32_t x, int32_t y);
334 void onMouseMoveSecondary(int32_t dx, int32_t dy);
335 void onMouseWheel(int32_t xDelta, int32_t yDelta);
336
337 // add client to list and attach event handlers for client
338 bool addClient(BaseClientProxy *);
339
340 // remove client from list and detach event handlers for client
341 bool removeClient(BaseClientProxy *);
342
343 // close a client
344 void closeClient(BaseClientProxy *, const char *msg);
345
346 // close clients not in \p config
347 void closeClients(const ServerConfig &config);
348
349 // close all clients whether they've completed the handshake or not,
350 // except the primary client
351 void closeAllClients();
352
353 // remove clients from internal state
354 void removeActiveClient(BaseClientProxy *);
355 void removeOldClient(BaseClientProxy *);
356
357 // force the cursor off of \p client
358 void forceLeaveClient(const BaseClientProxy *client);
359
360private:
361 class ClipboardInfo
362 {
363 public:
364 ClipboardInfo() = default;
365
366 public:
367 Clipboard m_clipboard;
368 std::string m_clipboardData;
369 std::string m_clipboardOwner;
370 uint32_t m_clipboardSeqNum = 0;
371 };
372 // Order suggested by clang
373
374 // the Primary Screen Client
375 PrimaryClient *m_primaryClient = nullptr;
376
377 // the client with focus
378 BaseClientProxy *m_active = nullptr;
379
380 // current configuration
381 ServerConfig *m_config = nullptr;
382
383 // input filter (from m_config);
384 InputFilter *m_inputFilter = nullptr;
385
386 // state saved when screen saver activates
387 BaseClientProxy *m_activeSaver = nullptr;
388
389 BaseClientProxy *m_switchScreen = nullptr;
390 double m_switchWaitDelay = 0.0;
391 EventQueueTimer *m_switchWaitTimer = nullptr;
392
393 // delay for double-tap screen switching
394 double m_switchTwoTapDelay = 0.0;
395
396 // server screen
397 deskflow::Screen *m_screen;
398
399 IEventQueue *m_events = nullptr;
400 size_t m_maximumClipboardSize = INT_MAX;
401 ClientListener *m_clientListener = nullptr;
402 Stopwatch m_switchTwoTapTimer;
403
404 // Name of screen broadcasting the keyboard events
405 std::string m_keyboardBroadcastingScreens;
406
407 // all clients (including the primary client) indexed by name
408 using ClientList = std::map<std::string, BaseClientProxy *>;
409 using ClientSet = std::set<BaseClientProxy *>;
410 ClientList m_clients;
411 ClientSet m_clientSet;
412
413 // all old connections that we're waiting to hangup
414 using OldClients = std::map<BaseClientProxy *, EventQueueTimer *>;
415 OldClients m_oldClients;
416
417 // clipboard cache
418 ClipboardInfo m_clipboards[kClipboardEnd];
419
420 // used in hello message sent to the client
422
423 // the sequence number of enter messages
424 uint32_t m_seqNum = 0;
425
426 // current mouse position (in absolute screen coordinates) on
427 // whichever screen is active
428 int32_t m_x;
429 int32_t m_y;
430
431 // last mouse deltas. this is needed to smooth out double tap
432 // on win32 which reports bogus mouse motion at the edge of
433 // the screen when using low level hooks, synthesizing motion
434 // in the opposite direction the mouse actually moved.
435 int32_t m_xDelta = 0;
436 int32_t m_yDelta = 0;
437 int32_t m_xDelta2 = 0;
438 int32_t m_yDelta2 = 0;
439
440 int32_t m_xSaver;
441 int32_t m_ySaver;
442
443 // state for delayed screen switching
444 int32_t m_switchWaitX;
445 int32_t m_switchWaitY;
446
447 int32_t m_switchTwoTapZone = 3;
448
449 // common state for screen switch tests. all tests are always
450 // trying to reach the same screen in the same direction.
451 Direction m_switchDir = Direction::NoDirection;
452
453 bool m_switchTwoTapEngaged = false;
454 bool m_switchTwoTapArmed = false;
455
456 // modifiers needed before switching
457 bool m_switchNeedsShift = false;
458 bool m_switchNeedsControl = false;
459 bool m_switchNeedsAlt = false;
460
461 // relative mouse move option
462 bool m_relativeMoves = false;
463
464 // flag whether or not we have broadcasting enabled and the screens to
465 // which we should send broadcasted keys.
466 bool m_keyboardBroadcasting = false;
467
468 // screen locking (former scroll lock)
469 bool m_lockedToScreen = false;
470
471 bool m_defaultLockToScreenState = false;
472 bool m_disableLockToScreen = false;
473 bool m_enableClipboard = true;
474};
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:14
@ Barrier
Definition NetworkProtocol.h:17
int y
Definition ServerConfig.cpp:25
int x
Definition ServerConfig.cpp:24
Generic proxy for client or primary.
Definition BaseClientProxy.h:18
Definition ClientListener.h:28
Memory buffer clipboard.
Definition Clipboard.h:17
EventData()=default
Definition EventQueueTimer.h:12
Event.
Definition Event.h:29
Event queue interface.
Definition IEventQueue.h:29
Definition InputFilter.h:23
Primary screen as pseudo-client.
Definition PrimaryClient.h:23
Definition ServerConfig.h:35
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
Server & operator=(Server const &)=delete
Server(ServerConfig &config, PrimaryClient *primaryClient, deskflow::Screen *screen, IEventQueue *events)
Definition Server.cpp:42
Server & operator=(Server &&)=delete
~Server()
Definition Server.cpp:143
void adoptClient(BaseClientProxy *client)
Add a client.
Definition Server.cpp:225
Server(Server &&)=delete
std::string protocolString() const
Get the network protocol.
Definition Server.cpp:274
bool setConfig(const ServerConfig &)
Set configuration.
Definition Server.cpp:185
void getClients(std::vector< std::string > &list) const
Get the list of connected clients.
Definition Server.cpp:286
void setListener(ClientListener *p)
Store ClientListener pointer.
Definition Server.h:174
uint32_t getNumClients() const
Get number of connected clients.
Definition Server.cpp:281
Server(Server const &)=delete
void disconnect()
Disconnect clients.
Definition Server.cpp:263
Thread handle.
Definition Thread.h:33
Platform independent screen.
Definition Screen.h:30
Server configuration.
Definition Config.h:52
Definition DaemonApp.h:20