Deskflow 1.24.0.365
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
57
58 public:
60 };
61
64 {
65 public:
66 static SwitchToScreenInfo *alloc(const std::string &screen);
67
68 public:
69 // this is a C-string; this type is a variable size structure
70 char m_screen[1];
71 };
72
75 {
76 public:
77 static SwitchInDirectionInfo *alloc(Direction direction);
78
79 public:
81 };
82
85 {
86 public:
87 explicit ScreenConnectedInfo(std::string screen) : m_screen(screen)
88 {
89 // do nothing
90 }
91
92 public:
93 std::string m_screen; // was char[1]
94 };
95
98 {
99 public:
100 enum State
101 {
105 };
106
107 static KeyboardBroadcastInfo *alloc(State state = kToggle);
108 static KeyboardBroadcastInfo *alloc(State state, const std::string &screens);
109
110 public:
112 char m_screens[1];
113 };
114
120 Server(ServerConfig &config, PrimaryClient *primaryClient, deskflow::Screen *screen, IEventQueue *events);
121 Server(Server const &) = delete;
122 Server(Server &&) = delete;
123 ~Server();
124
125 Server &operator=(Server const &) = delete;
126 Server &operator=(Server &&) = delete;
127
129
130
132
137 bool setConfig(const ServerConfig &);
138
140
144 void adoptClient(BaseClientProxy *client);
145
147
153 void disconnect();
154
157 {
158 m_clientListener = p;
159 }
160
162
164
166
169 std::string protocolString() const;
170
172
175 uint32_t getNumClients() const;
176
178
181 void getClients(std::vector<std::string> &list) const;
182
184
185private:
186 // get canonical name of client
187 std::string getName(const BaseClientProxy *) const;
188
189 // get the sides of the primary screen that have neighbors
190 uint32_t getActivePrimarySides() const;
191
192 // returns true iff mouse should be locked to the current screen
193 // according to this object only, ignoring what the primary client
194 // says.
195 bool isLockedToScreenServer() const;
196
197 // returns true iff mouse should be locked to the current screen
198 // according to this object or the primary client.
199 bool isLockedToScreen() const;
200
201 // returns the jump zone of the client
202 int32_t getJumpZoneSize(const BaseClientProxy *) const;
203
204 // change the active screen
205 void switchScreen(BaseClientProxy *, int32_t x, int32_t y, bool forScreenSaver);
206
207 // jump to screen
208 void jumpToScreen(BaseClientProxy *);
209
210 // convert pixel position to fraction, using x or y depending on the
211 // direction.
212 float mapToFraction(const BaseClientProxy *, Direction, int32_t x, int32_t y) const;
213
214 // convert fraction to pixel position, writing only x or y depending
215 // on the direction.
216 void mapToPixel(const BaseClientProxy *, Direction, float f, int32_t &x, int32_t &y) const;
217
218 // returns true if the client has a neighbor anywhere along the edge
219 // indicated by the direction.
220 bool hasAnyNeighbor(const BaseClientProxy *, Direction) const;
221
222 // lookup neighboring screen, mapping the coordinate independent of
223 // the direction to the neighbor's coordinate space.
224 BaseClientProxy *getNeighbor(const BaseClientProxy *, Direction, int32_t &x, int32_t &y) const;
225
226 // lookup neighboring screen. given a position relative to the
227 // source screen, find the screen we should move onto and where.
228 // if the position is sufficiently far from the source then we
229 // cross multiple screens. if there is no suitable screen then
230 // return nullptr and x,y are not modified.
231 BaseClientProxy *mapToNeighbor(BaseClientProxy *, Direction, int32_t &x, int32_t &y) const;
232
233 // adjusts x and y or neither to avoid ending up in a jump zone
234 // after entering the client in the given direction.
235 void avoidJumpZone(const BaseClientProxy *, Direction, int32_t &x, int32_t &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(BaseClientProxy *dst, Direction, int32_t x, int32_t y, int32_t xActive, int32_t yActive);
241
242 // update switch state due to a mouse move at \p x, \p y that
243 // doesn't switch screens.
244 void noSwitch(int32_t x, int32_t y);
245
246 // stop switch timers
247 void stopSwitch();
248
249 // start two tap switch timer
250 void startSwitchTwoTap();
251
252 // arm the two tap switch timer if \p x, \p y is outside the tap zone
253 void armSwitchTwoTap(int32_t x, int32_t y);
254
255 // stop the two tap switch timer
256 void stopSwitchTwoTap();
257
258 // returns true iff the two tap switch timer is started
259 bool isSwitchTwoTapStarted() const;
260
261 // returns true iff should switch because of two tap
262 bool shouldSwitchTwoTap() const;
263
264 // start delay switch timer
265 void startSwitchWait(int32_t x, int32_t y);
266
267 // stop delay switch timer
268 void stopSwitchWait();
269
270 // returns true iff the delay switch timer is started
271 bool isSwitchWaitStarted() const;
272
273 // returns the corner (EScreenSwitchCornerMasks) where x,y is on the
274 // given client. corners have the given size.
275 uint32_t getCorner(const BaseClientProxy *, int32_t x, int32_t y, int32_t size) const;
276
277 // stop relative mouse moves
278 void stopRelativeMoves();
279
280 // send screen options to \c client
281 void sendOptions(BaseClientProxy *client) const;
282
283 // process options from configuration
284 void processOptions();
285
286 // event handlers
287 void handleShapeChanged(BaseClientProxy *client);
288 void handleClipboardGrabbed(const Event &event, BaseClientProxy *client);
289 void handleClipboardChanged(const Event &event, BaseClientProxy *client);
290 void handleKeyDownEvent(const Event &event);
291 void handleKeyUpEvent(const Event &event);
292 void handleKeyRepeatEvent(const Event &event);
293 void handleButtonDownEvent(const Event &event);
294 void handleButtonUpEvent(const Event &event);
295 void handleMotionPrimaryEvent(const Event &event);
296 void handleMotionSecondaryEvent(const Event &event);
297 void handleWheelEvent(const Event &event);
298 void handleSwitchWaitTimeout();
299 void handleClientDisconnected(BaseClientProxy *client);
300 void handleClientCloseTimeout(BaseClientProxy *client);
301 void handleSwitchToScreenEvent(const Event &event);
302 void handleSwitchInDirectionEvent(const Event &event);
303 void handleToggleScreenEvent(const Event &);
304 void handleKeyboardBroadcastEvent(const Event &event);
305 void handleLockCursorToScreenEvent(const Event &event);
306
307 // event processing
308 void onClipboardChanged(const BaseClientProxy *sender, ClipboardID id, uint32_t seqNum);
309 void onScreensaver(bool activated);
310 void onKeyDown(KeyID, KeyModifierMask, KeyButton, const std::string &, const char *screens);
311 void onKeyUp(KeyID, KeyModifierMask, KeyButton, const char *screens);
312 void onKeyRepeat(KeyID, KeyModifierMask, int32_t, KeyButton, const std::string &);
313 void onMouseDown(ButtonID);
314 void onMouseUp(ButtonID);
315 bool onMouseMovePrimary(int32_t x, int32_t y);
316 void onMouseMoveSecondary(int32_t dx, int32_t dy);
317 void onMouseWheel(int32_t xDelta, int32_t yDelta);
318
319 // add client to list and attach event handlers for client
320 bool addClient(BaseClientProxy *);
321
322 // remove client from list and detach event handlers for client
323 bool removeClient(BaseClientProxy *);
324
325 // close a client
326 void closeClient(BaseClientProxy *, const char *msg);
327
328 // close clients not in \p config
329 void closeClients(const ServerConfig &config);
330
331 // close all clients whether they've completed the handshake or not,
332 // except the primary client
333 void closeAllClients();
334
335 // remove clients from internal state
336 void removeActiveClient(BaseClientProxy *);
337 void removeOldClient(BaseClientProxy *);
338
339 // force the cursor off of \p client
340 void forceLeaveClient(const BaseClientProxy *client);
341
342private:
343 class ClipboardInfo
344 {
345 public:
346 ClipboardInfo() = default;
347
348 public:
349 Clipboard m_clipboard;
350 std::string m_clipboardData;
351 std::string m_clipboardOwner;
352 uint32_t m_clipboardSeqNum = 0;
353 };
354 // Order suggested by clang
355
356 // the Primary Screen Client
357 PrimaryClient *m_primaryClient = nullptr;
358
359 // the client with focus
360 BaseClientProxy *m_active = nullptr;
361
362 // current configuration
363 ServerConfig *m_config = nullptr;
364
365 // input filter (from m_config);
366 InputFilter *m_inputFilter = nullptr;
367
368 // state saved when screen saver activates
369 BaseClientProxy *m_activeSaver = nullptr;
370
371 BaseClientProxy *m_switchScreen = nullptr;
372 double m_switchWaitDelay = 0.0;
373 EventQueueTimer *m_switchWaitTimer = nullptr;
374
375 // delay for double-tap screen switching
376 double m_switchTwoTapDelay = 0.0;
377
378 // server screen
379 deskflow::Screen *m_screen;
380
381 IEventQueue *m_events = nullptr;
382 size_t m_maximumClipboardSize = INT_MAX;
383 ClientListener *m_clientListener = nullptr;
384 Stopwatch m_switchTwoTapTimer;
385
386 // Name of screen broadcasting the keyboard events
387 std::string m_keyboardBroadcastingScreens;
388
389 // all clients (including the primary client) indexed by name
390 using ClientList = std::map<std::string, BaseClientProxy *>;
391 using ClientSet = std::set<BaseClientProxy *>;
392 ClientList m_clients;
393 ClientSet m_clientSet;
394
395 // all old connections that we're waiting to hangup
396 using OldClients = std::map<BaseClientProxy *, EventQueueTimer *>;
397 OldClients m_oldClients;
398
399 // clipboard cache
400 ClipboardInfo m_clipboards[kClipboardEnd];
401
402 // used in hello message sent to the client
404
405 // the sequence number of enter messages
406 uint32_t m_seqNum = 0;
407
408 // current mouse position (in absolute screen coordinates) on
409 // whichever screen is active
410 int32_t m_x;
411 int32_t m_y;
412
413 // last mouse deltas. this is needed to smooth out double tap
414 // on win32 which reports bogus mouse motion at the edge of
415 // the screen when using low level hooks, synthesizing motion
416 // in the opposite direction the mouse actually moved.
417 int32_t m_xDelta = 0;
418 int32_t m_yDelta = 0;
419 int32_t m_xDelta2 = 0;
420 int32_t m_yDelta2 = 0;
421
422 int32_t m_xSaver;
423 int32_t m_ySaver;
424
425 // state for delayed screen switching
426 int32_t m_switchWaitX;
427 int32_t m_switchWaitY;
428
429 int32_t m_switchTwoTapZone = 3;
430
431 // common state for screen switch tests. all tests are always
432 // trying to reach the same screen in the same direction.
433 Direction m_switchDir = Direction::NoDirection;
434
435 bool m_switchTwoTapEngaged = false;
436 bool m_switchTwoTapArmed = false;
437
438 // modifiers needed before switching
439 bool m_switchNeedsShift = false;
440 bool m_switchNeedsControl = false;
441 bool m_switchNeedsAlt = false;
442
443 // relative mouse move option
444 bool m_relativeMoves = false;
445
446 // flag whether or not we have broadcasting enabled and the screens to
447 // which we should send broadcasted keys.
448 bool m_keyboardBroadcasting = false;
449
450 // screen locking (former scroll lock)
451 bool m_lockedToScreen = false;
452
453 bool m_disableLockToScreen = false;
454 bool m_enableClipboard = true;
455};
static const ClipboardID kClipboardEnd
Definition ClipboardTypes.h:30
uint8_t ClipboardID
Clipboard ID.
Definition ClipboardTypes.h:16
Direction
Screen 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:10
@ Barrier
Definition NetworkProtocol.h:12
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
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
Keyboard broadcast data.
Definition Server.h:98
State m_state
Definition Server.h:111
static KeyboardBroadcastInfo * alloc(State state=kToggle)
Definition Server.cpp:2095
char m_screens[1]
Definition Server.h:112
State
Definition Server.h:101
@ kOff
Definition Server.h:102
@ kOn
Definition Server.h:103
@ kToggle
Definition Server.h:104
Lock cursor to screen data.
Definition Server.h:47
State
Definition Server.h:50
@ kOn
Definition Server.h:52
@ kToggle
Definition Server.h:53
@ kOff
Definition Server.h:51
static LockCursorToScreenInfo * alloc(State state=kToggle)
Definition Server.cpp:2062
State m_state
Definition Server.h:59
std::string m_screen
Definition Server.h:93
ScreenConnectedInfo(std::string screen)
Definition Server.h:87
Switch in direction data.
Definition Server.h:75
Direction m_direction
Definition Server.h:80
static SwitchInDirectionInfo * alloc(Direction direction)
Definition Server.cpp:2084
Switch to screen data.
Definition Server.h:64
char m_screen[1]
Definition Server.h:70
static SwitchToScreenInfo * alloc(const std::string &screen)
Definition Server.cpp:2073
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:140
void adoptClient(BaseClientProxy *client)
Add a client.
Definition Server.cpp:222
Server(Server &&)=delete
std::string protocolString() const
Get the network protocol.
Definition Server.cpp:271
bool setConfig(const ServerConfig &)
Set configuration.
Definition Server.cpp:182
void getClients(std::vector< std::string > &list) const
Get the list of connected clients.
Definition Server.cpp:287
void setListener(ClientListener *p)
Store ClientListener pointer.
Definition Server.h:156
uint32_t getNumClients() const
Get number of connected clients.
Definition Server.cpp:282
Server(Server const &)=delete
void disconnect()
Disconnect clients.
Definition Server.cpp:260
Thread handle.
Definition Thread.h:33
Platform independent screen.
Definition Screen.h:30
Server configuration.
Definition Config.h:52
Definition EventTypes.h:11