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