1 | /*
|
---|
2 | * synergy -- mouse and keyboard sharing utility
|
---|
3 | * Copyright (C) 2004 Chris Schoeneman
|
---|
4 | *
|
---|
5 | * This package is free software; you can redistribute it and/or
|
---|
6 | * modify it under the terms of the GNU General Public License
|
---|
7 | * found in the file COPYING that should have accompanied this file.
|
---|
8 | *
|
---|
9 | * This package is distributed in the hope that it will be useful,
|
---|
10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
|
---|
11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
---|
12 | * GNU General Public License for more details.
|
---|
13 | */
|
---|
14 |
|
---|
15 | #ifndef CMSWINDOWSDESKS_H
|
---|
16 | #define CMSWINDOWSDESKS_H
|
---|
17 |
|
---|
18 | #include "CSynergyHook.h"
|
---|
19 | #include "KeyTypes.h"
|
---|
20 | #include "MouseTypes.h"
|
---|
21 | #include "OptionTypes.h"
|
---|
22 | #include "CCondVar.h"
|
---|
23 | #include "CMutex.h"
|
---|
24 | #include "CString.h"
|
---|
25 | #include "stdmap.h"
|
---|
26 | #define WIN32_LEAN_AND_MEAN
|
---|
27 | #include <windows.h>
|
---|
28 |
|
---|
29 | class CEvent;
|
---|
30 | class CEventQueueTimer;
|
---|
31 | class CThread;
|
---|
32 | class IJob;
|
---|
33 | class IScreenSaver;
|
---|
34 |
|
---|
35 | //! Microsoft Windows desk handling
|
---|
36 | /*!
|
---|
37 | Desks in Microsoft Windows are only remotely like desktops on X11
|
---|
38 | systems. A desk is another virtual surface for windows but desks
|
---|
39 | impose serious restrictions: a thread can interact with only one
|
---|
40 | desk at a time, you can't switch desks if the thread has any hooks
|
---|
41 | installed or owns any windows, windows cannot exist on multiple
|
---|
42 | desks at once, etc. Basically, they're useless except for running
|
---|
43 | the login window or the screensaver, which is what they're used
|
---|
44 | for. Synergy must deal with them mainly because of the login
|
---|
45 | window and screensaver but users can create their own desks and
|
---|
46 | synergy should work on those too.
|
---|
47 |
|
---|
48 | This class encapsulates all the desk nastiness. Clients of this
|
---|
49 | object don't have to know anything about desks.
|
---|
50 | */
|
---|
51 | class CMSWindowsDesks {
|
---|
52 | public:
|
---|
53 | //! Constructor
|
---|
54 | /*!
|
---|
55 | \p isPrimary is true iff the desk is for a primary screen.
|
---|
56 | \p screensaver points to a screensaver object and it's used
|
---|
57 | only to check if the screensaver is active. The \p updateKeys
|
---|
58 | job is adopted and is called when the key state should be
|
---|
59 | updated in a thread attached to the current desk.
|
---|
60 | \p hookLibrary must be a handle to the hook library.
|
---|
61 | */
|
---|
62 | CMSWindowsDesks(bool isPrimary, HINSTANCE hookLibrary,
|
---|
63 | const IScreenSaver* screensaver, IJob* updateKeys);
|
---|
64 | ~CMSWindowsDesks();
|
---|
65 |
|
---|
66 | //! @name manipulators
|
---|
67 | //@{
|
---|
68 |
|
---|
69 | //! Enable desk tracking
|
---|
70 | /*!
|
---|
71 | Enables desk tracking. While enabled, this object checks to see
|
---|
72 | if the desk has changed and ensures that the hooks are installed
|
---|
73 | on the new desk. \c setShape should be called at least once
|
---|
74 | before calling \c enable.
|
---|
75 | */
|
---|
76 | void enable();
|
---|
77 |
|
---|
78 | //! Disable desk tracking
|
---|
79 | /*!
|
---|
80 | Disables desk tracking. \sa enable.
|
---|
81 | */
|
---|
82 | void disable();
|
---|
83 |
|
---|
84 | //! Notify of entering a desk
|
---|
85 | /*!
|
---|
86 | Prepares a desk for when the cursor enters it.
|
---|
87 | */
|
---|
88 | void enter();
|
---|
89 |
|
---|
90 | //! Notify of leaving a desk
|
---|
91 | /*!
|
---|
92 | Prepares a desk for when the cursor leaves it.
|
---|
93 | */
|
---|
94 | void leave(HKL keyLayout);
|
---|
95 |
|
---|
96 | //! Notify of options changes
|
---|
97 | /*!
|
---|
98 | Resets all options to their default values.
|
---|
99 | */
|
---|
100 | void resetOptions();
|
---|
101 |
|
---|
102 | //! Notify of options changes
|
---|
103 | /*!
|
---|
104 | Set options to given values. Ignores unknown options and doesn't
|
---|
105 | modify options that aren't given in \c options.
|
---|
106 | */
|
---|
107 | void setOptions(const COptionsList& options);
|
---|
108 |
|
---|
109 | //! Update the key state
|
---|
110 | /*!
|
---|
111 | Causes the key state to get updated to reflect the physical keyboard
|
---|
112 | state and current keyboard mapping.
|
---|
113 | */
|
---|
114 | void updateKeys();
|
---|
115 |
|
---|
116 | //! Tell desk about new size
|
---|
117 | /*!
|
---|
118 | This tells the desks that the display size has changed.
|
---|
119 | */
|
---|
120 | void setShape(SInt32 x, SInt32 y,
|
---|
121 | SInt32 width, SInt32 height,
|
---|
122 | SInt32 xCenter, SInt32 yCenter, bool isMultimon);
|
---|
123 |
|
---|
124 | //! Install/uninstall screensaver hooks
|
---|
125 | /*!
|
---|
126 | If \p install is true then the screensaver hooks are installed and,
|
---|
127 | if desk tracking is enabled, updated whenever the desk changes. If
|
---|
128 | \p install is false then the screensaver hooks are uninstalled.
|
---|
129 | */
|
---|
130 | void installScreensaverHooks(bool install);
|
---|
131 |
|
---|
132 | //! Start ignoring user input
|
---|
133 | /*!
|
---|
134 | Starts ignoring user input so we don't pick up our own synthesized events.
|
---|
135 | */
|
---|
136 | void fakeInputBegin();
|
---|
137 |
|
---|
138 | //! Stop ignoring user input
|
---|
139 | /*!
|
---|
140 | Undoes whatever \c fakeInputBegin() did.
|
---|
141 | */
|
---|
142 | void fakeInputEnd();
|
---|
143 |
|
---|
144 | //@}
|
---|
145 | //! @name accessors
|
---|
146 | //@{
|
---|
147 |
|
---|
148 | //! Get cursor position
|
---|
149 | /*!
|
---|
150 | Return the current position of the cursor in \c x and \c y.
|
---|
151 | */
|
---|
152 | void getCursorPos(SInt32& x, SInt32& y) const;
|
---|
153 |
|
---|
154 | //! Fake key press/release
|
---|
155 | /*!
|
---|
156 | Synthesize a press or release of key \c button.
|
---|
157 | */
|
---|
158 | void fakeKeyEvent(KeyButton button, UINT virtualKey,
|
---|
159 | bool press, bool isAutoRepeat) const;
|
---|
160 |
|
---|
161 | //! Fake mouse press/release
|
---|
162 | /*!
|
---|
163 | Synthesize a press or release of mouse button \c id.
|
---|
164 | */
|
---|
165 | void fakeMouseButton(ButtonID id, bool press) const;
|
---|
166 |
|
---|
167 | //! Fake mouse move
|
---|
168 | /*!
|
---|
169 | Synthesize a mouse move to the absolute coordinates \c x,y.
|
---|
170 | */
|
---|
171 | void fakeMouseMove(SInt32 x, SInt32 y) const;
|
---|
172 |
|
---|
173 | //! Fake mouse move
|
---|
174 | /*!
|
---|
175 | Synthesize a mouse move to the relative coordinates \c dx,dy.
|
---|
176 | */
|
---|
177 | void fakeMouseRelativeMove(SInt32 dx, SInt32 dy) const;
|
---|
178 |
|
---|
179 | //! Fake mouse wheel
|
---|
180 | /*!
|
---|
181 | Synthesize a mouse wheel event of amount \c delta in direction \c axis.
|
---|
182 | */
|
---|
183 | void fakeMouseWheel(SInt32 xDelta, SInt32 yDelta) const;
|
---|
184 |
|
---|
185 | //@}
|
---|
186 |
|
---|
187 | private:
|
---|
188 | class CDesk {
|
---|
189 | public:
|
---|
190 | CString m_name;
|
---|
191 | CThread* m_thread;
|
---|
192 | DWORD m_threadID;
|
---|
193 | DWORD m_targetID;
|
---|
194 | HDESK m_desk;
|
---|
195 | HWND m_window;
|
---|
196 | HWND m_foregroundWindow;
|
---|
197 | bool m_lowLevel;
|
---|
198 | };
|
---|
199 | typedef std::map<CString, CDesk*> CDesks;
|
---|
200 |
|
---|
201 | // initialization and shutdown operations
|
---|
202 | void queryHookLibrary(HINSTANCE hookLibrary);
|
---|
203 | HCURSOR createBlankCursor() const;
|
---|
204 | void destroyCursor(HCURSOR cursor) const;
|
---|
205 | ATOM createDeskWindowClass(bool isPrimary) const;
|
---|
206 | void destroyClass(ATOM windowClass) const;
|
---|
207 | HWND createWindow(ATOM windowClass, const char* name) const;
|
---|
208 | void destroyWindow(HWND) const;
|
---|
209 |
|
---|
210 | // message handlers
|
---|
211 | void deskMouseMove(SInt32 x, SInt32 y) const;
|
---|
212 | void deskMouseRelativeMove(SInt32 dx, SInt32 dy) const;
|
---|
213 | void deskEnter(CDesk* desk);
|
---|
214 | void deskLeave(CDesk* desk, HKL keyLayout);
|
---|
215 | void deskThread(void* vdesk);
|
---|
216 |
|
---|
217 | // desk switch checking and handling
|
---|
218 | CDesk* addDesk(const CString& name, HDESK hdesk);
|
---|
219 | void removeDesks();
|
---|
220 | void checkDesk();
|
---|
221 | bool isDeskAccessible(const CDesk* desk) const;
|
---|
222 | void handleCheckDesk(const CEvent& event, void*);
|
---|
223 |
|
---|
224 | // communication with desk threads
|
---|
225 | void waitForDesk() const;
|
---|
226 | void sendMessage(UINT, WPARAM, LPARAM) const;
|
---|
227 |
|
---|
228 | // work around for messed up keyboard events from low-level hooks
|
---|
229 | HWND getForegroundWindow() const;
|
---|
230 |
|
---|
231 | // desk API wrappers
|
---|
232 | HDESK openInputDesktop();
|
---|
233 | void closeDesktop(HDESK);
|
---|
234 | CString getDesktopName(HDESK);
|
---|
235 |
|
---|
236 | // our desk window procs
|
---|
237 | static LRESULT CALLBACK primaryDeskProc(HWND, UINT, WPARAM, LPARAM);
|
---|
238 | static LRESULT CALLBACK secondaryDeskProc(HWND, UINT, WPARAM, LPARAM);
|
---|
239 |
|
---|
240 | private:
|
---|
241 | // true if screen is being used as a primary screen, false otherwise
|
---|
242 | bool m_isPrimary;
|
---|
243 |
|
---|
244 | // true if windows 95/98/me
|
---|
245 | bool m_is95Family;
|
---|
246 |
|
---|
247 | // true if windows 98/2k or higher (i.e. not 95/nt)
|
---|
248 | bool m_isModernFamily;
|
---|
249 |
|
---|
250 | // true if mouse has entered the screen
|
---|
251 | bool m_isOnScreen;
|
---|
252 |
|
---|
253 | // our resources
|
---|
254 | ATOM m_deskClass;
|
---|
255 | HCURSOR m_cursor;
|
---|
256 |
|
---|
257 | // screen shape stuff
|
---|
258 | SInt32 m_x, m_y;
|
---|
259 | SInt32 m_w, m_h;
|
---|
260 | SInt32 m_xCenter, m_yCenter;
|
---|
261 |
|
---|
262 | // true if system appears to have multiple monitors
|
---|
263 | bool m_multimon;
|
---|
264 |
|
---|
265 | // the timer used to check for desktop switching
|
---|
266 | CEventQueueTimer* m_timer;
|
---|
267 |
|
---|
268 | // screen saver stuff
|
---|
269 | DWORD m_threadID;
|
---|
270 | const IScreenSaver* m_screensaver;
|
---|
271 | bool m_screensaverNotify;
|
---|
272 |
|
---|
273 | // the current desk and it's name
|
---|
274 | CDesk* m_activeDesk;
|
---|
275 | CString m_activeDeskName;
|
---|
276 |
|
---|
277 | // one desk per desktop and a cond var to communicate with it
|
---|
278 | CMutex m_mutex;
|
---|
279 | CCondVar<bool> m_deskReady;
|
---|
280 | CDesks m_desks;
|
---|
281 |
|
---|
282 | // hook library stuff
|
---|
283 | InstallFunc m_install;
|
---|
284 | UninstallFunc m_uninstall;
|
---|
285 | InstallScreenSaverFunc m_installScreensaver;
|
---|
286 | UninstallScreenSaverFunc m_uninstallScreensaver;
|
---|
287 |
|
---|
288 | // keyboard stuff
|
---|
289 | IJob* m_updateKeys;
|
---|
290 | HKL m_keyLayout;
|
---|
291 |
|
---|
292 | // options
|
---|
293 | bool m_leaveForegroundOption;
|
---|
294 | };
|
---|
295 |
|
---|
296 | #endif
|
---|