Deskflow 1.26.0.418
Keyboard and mouse sharing utility
Loading...
Searching...
No Matches
OSXScreen.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 - 2016 Synergy App Ltd
5 * SPDX-FileCopyrightText: (C) 2004 Chris Schoeneman
6 * SPDX-License-Identifier: GPL-2.0-only WITH LicenseRef-OpenSSL-Exception
7 */
8
9#pragma once
10
14
15#include <Carbon/Carbon.h>
16#include <IOKit/IOMessage.h>
17#include <mach/mach_init.h>
18#include <mach/mach_interface.h>
19#include <mach/mach_port.h>
20
21#include <bitset>
22#include <map>
23#include <memory>
24#include <thread>
25#include <vector>
26
27extern "C"
28{
29 using CGSConnectionID = int;
30 CGError CGSSetConnectionProperty(CGSConnectionID cid, CGSConnectionID targetCID, CFStringRef key, CFTypeRef value);
32}
33
34template <class T> class CondVar;
35class EventQueueTimer;
36class Mutex;
37class Thread;
38class OSXKeyState;
39class OSXScreenSaver;
40class IEventQueue;
41class Mutex;
42
45{
46public:
47 OSXScreen(IEventQueue *events, bool isPrimary, bool enableLangSync = false);
48
49 virtual ~OSXScreen();
50
52 {
53 return m_events;
54 }
55
56 // IScreen overrides
57 void *getEventTarget() const override;
58 bool getClipboard(ClipboardID id, IClipboard *) const override;
59 void getShape(int32_t &x, int32_t &y, int32_t &width, int32_t &height) const override;
60 void getCursorPos(int32_t &x, int32_t &y) const override;
61
62 // IPrimaryScreen overrides
63 void reconfigure(uint32_t activeSides) override;
64 uint32_t activeSides() override;
65 void warpCursor(int32_t x, int32_t y) override;
66 uint32_t registerHotKey(KeyID key, KeyModifierMask mask) override;
67 void unregisterHotKey(uint32_t id) override;
68 void fakeInputBegin() override;
69 void fakeInputEnd() override;
70 int32_t getJumpZoneSize() const override;
71 bool isAnyMouseButtonDown(uint32_t &buttonID) const override;
72 void getCursorCenter(int32_t &x, int32_t &y) const override;
73
74 // ISecondaryScreen overrides
75 void fakeMouseButton(ButtonID id, bool press) override;
76 void fakeMouseMove(int32_t x, int32_t y) override;
77 void fakeMouseRelativeMove(int32_t dx, int32_t dy) const override;
78 void fakeMouseWheel(ScrollDelta delta) const override;
79
80 // IPlatformScreen overrides
81 void enable() override;
82 void disable() override;
83 void enter() override;
84 bool canLeave() override;
85 void leave() override;
86 bool setClipboard(ClipboardID, const IClipboard *) override;
87 void checkClipboards() override;
88 void openScreensaver(bool notify) override;
89 void closeScreensaver() override;
90 void screensaver(bool activate) override;
91 void resetOptions() override;
92 void setOptions(const OptionsList &options) override;
93 void setSequenceNumber(uint32_t) override;
94 bool isPrimary() const override;
95 std::string getSecureInputApp() const override;
96
97 void waitForCarbonLoop() const;
98
99protected:
100 // IPlatformScreen overrides
101 void handleSystemEvent(const Event &e) override;
102 void updateButtons() override;
103 IKeyState *getKeyState() const override;
104
105private:
106 bool updateScreenShape();
107 bool updateScreenShape(const CGDirectDisplayID, const CGDisplayChangeSummaryFlags);
108 void postMouseEvent(CGPoint &) const;
109
110 // convenience function to send events
111 void sendEvent(EventTypes type, void * = nullptr) const;
112 void sendClipboardEvent(EventTypes type, ClipboardID id) const;
113
114 // message handlers
115 bool onMouseMove(CGEventRef event);
116 // mouse button handler. pressed is true if this is a mousedown
117 // event, false if it is a mouseup event. macButton is the index
118 // of the button pressed using the mac button mapping.
119 bool onMouseButton(bool pressed, uint16_t macButton);
120 bool onMouseWheel(int32_t xDelta, int32_t yDelta) const;
121
122 void constructMouseButtonEventMap();
123
124 bool onKey(CGEventRef event);
125
126 void onMediaKey(CGEventRef event);
127
128 bool onHotKey(EventRef event) const;
129
130 // Added here to allow the carbon cursor hack to be called.
131 void showCursor();
132 void hideCursor();
133
134 // map deskflow mouse button to mac buttons
135 ButtonID mapDeskflowButtonToMac(uint16_t) const;
136
137 // map mac mouse button to deskflow buttons
138 ButtonID mapMacButtonToDeskflow(uint16_t) const;
139
140 // map mac scroll wheel value to a deskflow scroll wheel value
141 int32_t mapScrollWheelToDeskflow(int32_t) const;
142
143 // get the current scroll wheel speed
144 double getScrollSpeed() const;
145
146 // Resolution switch callback
147 static void displayReconfigurationCallback(CGDirectDisplayID, CGDisplayChangeSummaryFlags, void *);
148
149 // fast user switch callback
150 static pascal OSStatus userSwitchCallback(EventHandlerCallRef nextHandler, EventRef theEvent, void *inUserData);
151
152 // sleep / wakeup support
153 void watchSystemPowerThread(const void *);
154 static void testCanceled(CFRunLoopTimerRef timer, void *info);
155 static void powerChangeCallback(void *refcon, io_service_t service, natural_t messageType, void *messageArgument);
156 void handlePowerChangeRequest(natural_t messageType, void *messageArgument);
157
158 void handleConfirmSleep(const Event &event);
159
160 bool checkAXPermissions();
161
162 // global hotkey operating mode
163 static bool isGlobalHotKeyOperatingModeAvailable();
164 static void setGlobalHotKeysEnabled(bool enabled);
165 static bool getGlobalHotKeysEnabled();
166
167 // Quartz event tap support
168 static CGEventRef handleCGInputEvent(CGEventTapProxy proxy, CGEventType type, CGEventRef event, void *refcon);
169 static CGEventRef
170 handleCGInputEventSecondary(CGEventTapProxy proxy, CGEventType type, CGEventRef event, void *refcon);
171
172 // convert CFString to char*
173 static char *CFStringRefToUTF8String(CFStringRef aString);
174
175private:
176 struct HotKeyItem
177 {
178 public:
179 HotKeyItem(uint32_t, uint32_t);
180 HotKeyItem(EventHotKeyRef, uint32_t, uint32_t);
181
182 EventHotKeyRef getRef() const;
183
184 bool operator<(const HotKeyItem &) const;
185
186 private:
187 EventHotKeyRef m_ref;
188 uint32_t m_keycode;
189 uint32_t m_mask;
190 };
191
192 enum EMouseButtonState
193 {
194 kMouseButtonUp = 0,
195 kMouseButtonDragged,
196 kMouseButtonDown,
197 kMouseButtonStateMax
198 };
199
200 class MouseButtonState
201 {
202 public:
203 void set(uint32_t button, EMouseButtonState state);
204 bool any();
205 void reset();
206 void overwrite(uint32_t buttons);
207
208 bool test(uint32_t button) const;
209 int8_t getFirstButtonDown() const;
210
211 private:
212 std::bitset<NumButtonIDs> m_buttons;
213 };
214
215 using HotKeyMap = std::map<uint32_t, HotKeyItem>;
216 using HotKeyIDList = std::vector<uint32_t>;
217 using ModifierHotKeyMap = std::map<KeyModifierMask, uint32_t>;
218 using HotKeyToIDMap = std::map<HotKeyItem, uint32_t>;
219
220 // true if screen is being used as a primary screen, false otherwise
221 bool m_isPrimary;
222
223 // true if mouse has entered the screen
224 bool m_isOnScreen;
225
226 // the display
227 CGDirectDisplayID m_displayID;
228
229 uint32_t m_activeSides = 0;
230 // screen shape stuff
231 int32_t m_x, m_y;
232 int32_t m_w, m_h;
233 int32_t m_xCenter, m_yCenter;
234
235 // mouse state
236 mutable int32_t m_xCursor, m_yCursor;
237 mutable bool m_cursorPosValid;
238
239 // mouse event number (needed for macOS 27)
240 uint32_t m_mouseEventNumber = 0;
241
242 /* FIXME: this data structure is explicitly marked mutable due
243 to a need to track the state of buttons since the remote
244 side only lets us know of change events, and because the
245 fakeMouseButton button method is marked 'const'. This is
246 Evil, and this should be moved to a place where it need not
247 be mutable as soon as possible. */
248 mutable MouseButtonState m_buttonState;
249 using MouseButtonEventMapType = std::map<uint16_t, CGEventType>;
250 std::vector<MouseButtonEventMapType> MouseButtonEventMap;
251
252 bool m_cursorHidden;
253
254 // keyboard stuff
255 OSXKeyState *m_keyState;
256
257 // clipboards
258 OSXClipboard m_pasteboard;
259 uint32_t m_sequenceNumber;
260
261 // screen saver stuff
262 OSXScreenSaver *m_screensaver;
263 bool m_screensaverNotify;
264
265 // clipboard stuff
266 bool m_ownClipboard;
267 EventQueueTimer *m_clipboardTimer;
268
269 EventQueueTimer *m_axTimer;
270
271 // window object that gets user input events when the server
272 // has focus.
273 WindowRef m_hiddenWindow;
274 // window object that gets user input events when the server
275 // does not have focus.
276 WindowRef m_userInputWindow;
277
278 // fast user switching
279 EventHandlerRef m_switchEventHandlerRef;
280
281 // sleep / wakeup
282 Mutex *m_pmMutex;
283 Thread *m_pmWatchThread;
284 CondVar<bool> *m_pmThreadReady;
285 CFRunLoopRef m_pmRunloop;
286 io_connect_t m_pmRootPort;
287
288 // hot key stuff
289 HotKeyMap m_hotKeys;
290 HotKeyIDList m_oldHotKeyIDs;
291 ModifierHotKeyMap m_modifierHotKeys;
292 uint32_t m_activeModifierHotKey;
293 KeyModifierMask m_activeModifierHotKeyMask;
294 HotKeyToIDMap m_hotKeyToIDMap;
295
296 // global hotkey operating mode
297 static bool s_testedForGHOM;
298 static bool s_hasGHOM;
299
300 // Quartz input event support
301 CFMachPortRef m_eventTapPort;
302 CFRunLoopSourceRef m_eventTapRLSR;
303 std::thread m_eventTapThread;
304 CFRunLoopRef m_eventTapRunLoop = nullptr;
305
306 // for double click coalescing.
307 double m_lastClickTime;
308 int m_clickState;
309 int32_t m_lastSingleClickXCursor;
310 int32_t m_lastSingleClickYCursor;
311
312 IEventQueue *m_events;
313
314 std::unique_ptr<Thread> m_getDropTargetThread;
315 std::string m_dropTarget;
316
317 Mutex *m_carbonLoopMutex;
318 CondVar<bool> *m_carbonLoopReady;
319
320 OSXPowerManager m_powerManager;
321
322 class OSXScreenImpl *m_impl;
323};
static int type
Definition ArchNetworkWinsock.cpp:46
uint8_t ClipboardID
Clipboard ID.
Definition ClipboardTypes.h:16
Coordinate ScrollDelta
Definition Coordinate.h:21
uint32_t KeyID
Key ID.
Definition KeyTypes.h:21
uint32_t KeyModifierMask
Modifier key mask.
Definition KeyTypes.h:44
uint8_t ButtonID
Mouse button ID.
Definition MouseTypes.h:16
CGError CGSSetConnectionProperty(CGSConnectionID cid, CGSConnectionID targetCID, CFStringRef key, CFTypeRef value)
int CGSConnectionID
Definition OSXScreen.h:29
int _CGSDefaultConnection()
std::vector< uint32_t > OptionsList
Definition OptionTypes.h:26
Condition variable.
Definition CondVar.h:121
Definition EventQueueTimer.h:12
Event.
Definition Event.h:43
Clipboard interface.
Definition IClipboard.h:19
Event queue interface.
Definition IEventQueue.h:29
Key state interface.
Definition IKeyState.h:23
Mutual exclusion.
Definition Mutex.h:22
OS X key state.
Definition OSXKeyState.h:25
OSX screen saver implementation.
Definition OSXScreenSaver.h:18
void fakeMouseMove(int32_t x, int32_t y) override
Fake mouse move.
Definition OSXScreen.mm:587
std::string getSecureInputApp() const override
Determine the name of the app causing a secure input state.
Definition OSXScreen.mm:1827
void unregisterHotKey(uint32_t id) override
Unregister a system hotkey.
Definition OSXScreen.mm:375
uint32_t registerHotKey(KeyID key, KeyModifierMask mask) override
Register a system hotkey.
Definition OSXScreen.mm:322
bool canLeave() override
Leave screen.
Definition OSXScreen.mm:818
void handleSystemEvent(const Event &e) override
Handle system event.
Definition OSXScreen.mm:916
void enter() override
Enter screen.
Definition OSXScreen.mm:792
OSXScreen(IEventQueue *events, bool isPrimary, bool enableLangSync=false)
Definition OSXScreen.mm:86
uint32_t activeSides() override
activeSides
Definition OSXScreen.mm:264
void getCursorCenter(int32_t &x, int32_t &y) const override
Get cursor center position.
Definition OSXScreen.mm:316
void fakeInputEnd() override
Done synthesizing input on primary screen.
Definition OSXScreen.mm:296
void enable() override
Enable screen.
Definition OSXScreen.mm:692
void * getEventTarget() const override
Get event target.
Definition OSXScreen.mm:226
void reconfigure(uint32_t activeSides) override
Update configuration.
Definition OSXScreen.mm:257
void disable() override
Disable screen.
Definition OSXScreen.mm:751
void fakeMouseRelativeMove(int32_t dx, int32_t dy) const override
Fake mouse move.
Definition OSXScreen.mm:601
void screensaver(bool activate) override
Activate/deactivate screen saver.
Definition OSXScreen.mm:874
void setSequenceNumber(uint32_t) override
Set clipboard sequence number.
Definition OSXScreen.mm:893
bool isAnyMouseButtonDown(uint32_t &buttonID) const override
Test if mouse is pressed.
Definition OSXScreen.mm:306
void warpCursor(int32_t x, int32_t y) override
Warp cursor.
Definition OSXScreen.mm:269
void fakeMouseButton(ButtonID id, bool press) override
Fake mouse press/release.
Definition OSXScreen.mm:504
void leave() override
Leave screen.
Definition OSXScreen.mm:823
void openScreensaver(bool notify) override
Open screen saver.
Definition OSXScreen.mm:859
void getCursorPos(int32_t &x, int32_t &y) const override
Get cursor position.
Definition OSXScreen.mm:245
void getShape(int32_t &x, int32_t &y, int32_t &width, int32_t &height) const override
Get screen shape.
Definition OSXScreen.mm:237
void checkClipboards() override
Check clipboard owner.
Definition OSXScreen.mm:849
int32_t getJumpZoneSize() const override
Get jump zone size.
Definition OSXScreen.mm:301
bool setClipboard(ClipboardID, const IClipboard *) override
Set clipboard.
Definition OSXScreen.mm:840
bool isPrimary() const override
Test if is primary screen.
Definition OSXScreen.mm:898
IEventQueue * getEvents() const
Definition OSXScreen.h:51
void fakeMouseWheel(ScrollDelta delta) const override
Synthesize a mouse wheel event of amount This Implmentation for this method should call applyScrollMo...
Definition OSXScreen.mm:625
void closeScreensaver() override
Close screen saver.
Definition OSXScreen.mm:867
bool getClipboard(ClipboardID id, IClipboard *) const override
Get clipboard.
Definition OSXScreen.mm:231
void setOptions(const OptionsList &options) override
Notify of options changes.
Definition OSXScreen.mm:888
void waitForCarbonLoop() const
Definition OSXScreen.mm:1805
IKeyState * getKeyState() const override
Get the key state.
Definition OSXScreen.mm:1305
void fakeInputBegin() override
Prepare to synthesize input on primary screen.
Definition OSXScreen.mm:291
void resetOptions() override
Notify of options changes.
Definition OSXScreen.mm:883
void updateButtons() override
Update mouse buttons.
Definition OSXScreen.mm:1298
PlatformScreen(IEventQueue *events)
Definition PlatformScreen.cpp:13
Thread handle.
Definition Thread.h:33
EventTypes
Definition EventTypes.h:13