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