deskflow/src/lib/platform/MSWindowsScreen.h

342 lines
10 KiB
C
Raw Normal View History

2012-06-10 16:50:54 +00:00
/*
* Deskflow -- mouse and keyboard sharing utility
* SPDX-FileCopyrightText: (C) 2025 Deskflow Developers
* SPDX-FileCopyrightText: (C) 2012 - 2016 Symless Ltd.
* SPDX-FileCopyrightText: (C) 2002 Chris Schoeneman
* SPDX-License-Identifier: GPL-2.0-only WITH LicenseRef-OpenSSL-Exception
2012-06-10 16:50:54 +00:00
*/
#pragma once
2012-06-10 16:50:54 +00:00
#include "deskflow/PlatformScreen.h"
#include "platform/MSWindowsHook.h"
#include "platform/MSWindowsPowerManager.h"
2012-06-10 16:50:54 +00:00
#include <map>
#include <string>
2012-06-10 16:50:54 +00:00
#define WIN32_LEAN_AND_MEAN
#include <Windows.h>
2012-06-10 16:50:54 +00:00
2014-11-11 13:51:47 +00:00
class EventQueueTimer;
2014-11-12 11:44:29 +00:00
class MSWindowsDesks;
class MSWindowsKeyState;
class MSWindowsScreenSaver;
2014-11-11 13:51:47 +00:00
class Thread;
2014-11-12 11:44:29 +00:00
class MSWindowsDropTarget;
2012-06-10 16:50:54 +00:00
//! Implementation of IPlatformScreen for Microsoft Windows
class MSWindowsScreen : public PlatformScreen
{
2012-06-10 16:50:54 +00:00
public:
MSWindowsScreen(
bool isPrimary, bool useHooks, IEventQueue *events, bool enableLangSync = false, bool invetScrolling = false
);
~MSWindowsScreen() override;
//! @name manipulators
//@{
//! Initialize
/*!
Saves the application's HINSTANCE. This \b must be called by
WinMain with the HINSTANCE it was passed.
*/
static void init(HINSTANCE);
//@}
//! @name accessors
//@{
//! Get instance
/*!
Returns the application instance handle passed to init().
*/
static HINSTANCE getWindowInstance();
//@}
// IScreen overrides
void *getEventTarget() const override;
bool getClipboard(ClipboardID id, IClipboard *) const override;
void getShape(int32_t &x, int32_t &y, int32_t &width, int32_t &height) const override;
void getCursorPos(int32_t &x, int32_t &y) const override;
/**
* \brief Get the position of the cursor on the current machine
* \param pos the object that the function will use to store the position of
* the cursor \return true if the function was successful
*/
virtual bool getThisCursorPos(LPPOINT pos);
/**
* \brief Sets the cursor position on the current machine
* \param x The x coordinate of the cursor
* \param y The Y coordinate of the cursor
* \return True is successful
*/
virtual bool setThisCursorPos(int x, int y);
/**
* \brief This function will attempt to switch to the current desktop the
* mouse is located on
*/
virtual void updateDesktopThread();
// IPrimaryScreen overrides
void reconfigure(uint32_t activeSides) override;
uint32_t activeSides() override;
void warpCursor(int32_t x, int32_t y) override;
uint32_t registerHotKey(KeyID key, KeyModifierMask mask) override;
void unregisterHotKey(uint32_t id) override;
void fakeInputBegin() override;
void fakeInputEnd() override;
int32_t getJumpZoneSize() const override;
bool isAnyMouseButtonDown(uint32_t &buttonID) const override;
void getCursorCenter(int32_t &x, int32_t &y) const override;
// ISecondaryScreen overrides
void fakeMouseButton(ButtonID id, bool press) override;
void fakeMouseMove(int32_t x, int32_t y) override;
void fakeMouseRelativeMove(int32_t dx, int32_t dy) const override;
void fakeMouseWheel(int32_t xDelta, int32_t yDelta) const override;
// IKeyState overrides
virtual void updateKeys();
void fakeKeyDown(KeyID id, KeyModifierMask mask, KeyButton button, const std::string &lang) override;
bool fakeKeyRepeat(KeyID id, KeyModifierMask mask, int32_t count, KeyButton button, const std::string &lang) override;
bool fakeKeyUp(KeyButton button) override;
void fakeAllKeysUp() override;
// IPlatformScreen overrides
void enable() override;
void disable() override;
void enter() override;
bool canLeave() override;
void leave() override;
bool setClipboard(ClipboardID, const IClipboard *) override;
void checkClipboards() override;
void openScreensaver(bool notify) override;
void closeScreensaver() override;
void screensaver(bool activate) override;
void resetOptions() override;
void setOptions(const OptionsList &options) override;
void setSequenceNumber(uint32_t) override;
bool isPrimary() const override;
std::string getSecureInputApp() const override;
2012-06-10 16:50:54 +00:00
protected:
// IPlatformScreen overrides
void handleSystemEvent(const Event &event) override;
void updateButtons() override;
IKeyState *getKeyState() const override;
2012-06-10 16:50:54 +00:00
// simulate a local key to the system directly
void fakeLocalKey(KeyButton button, bool press) const;
2012-06-10 16:50:54 +00:00
private:
// initialization and shutdown operations
HCURSOR createBlankCursor() const;
void destroyCursor(HCURSOR cursor) const;
ATOM createWindowClass() const;
ATOM createDeskWindowClass(bool isPrimary) const;
void destroyClass(ATOM windowClass) const;
HWND createWindow(ATOM windowClass, const wchar_t *name) const;
void destroyWindow(HWND) const;
// convenience function to send events
2012-06-10 16:50:54 +00:00
public: // HACK
void sendEvent(EventTypes type, void * = nullptr);
2012-06-10 16:50:54 +00:00
private: // HACK
void sendClipboardEvent(EventTypes type, ClipboardID id);
2012-06-10 16:50:54 +00:00
// handle message before it gets dispatched. returns true iff
// the message should not be dispatched.
bool onPreDispatch(HWND, UINT, WPARAM, LPARAM);
2012-06-10 16:50:54 +00:00
// handle message before it gets dispatched. returns true iff
// the message should not be dispatched.
bool onPreDispatchPrimary(HWND, UINT, WPARAM, LPARAM);
2012-06-10 16:50:54 +00:00
// handle secondary message before it gets dispatched. returns true iff
// the message should not be dispatched.
bool onPreDispatchSecondary(HWND, UINT, WPARAM, LPARAM);
// handle message. returns true iff handled and optionally sets
// \c *result (which defaults to 0).
bool onEvent(HWND, UINT, WPARAM, LPARAM, LRESULT *result);
2012-06-10 16:50:54 +00:00
// message handlers
2025-01-11 02:13:19 +00:00
bool onMark(uint32_t mark);
bool onKey(WPARAM, LPARAM);
bool onHotKey(WPARAM, LPARAM);
bool onMouseButton(WPARAM, LPARAM);
2025-01-11 01:11:56 +00:00
bool onMouseMove(int32_t x, int32_t y);
bool onMouseWheel(int32_t xDelta, int32_t yDelta);
bool onScreensaver(bool activated);
bool onDisplayChange();
void onClipboardChange();
2012-06-10 16:50:54 +00:00
// warp cursor without discarding queued events
2025-01-11 01:11:56 +00:00
void warpCursorNoFlush(int32_t x, int32_t y);
2012-06-10 16:50:54 +00:00
// discard posted messages
void nextMark();
2012-06-10 16:50:54 +00:00
// test if event should be ignored
bool ignore() const;
2012-06-10 16:50:54 +00:00
// update screen size cache
void updateScreenShape();
2012-06-10 16:50:54 +00:00
// fix timer callback
void handleFixes();
2012-06-10 16:50:54 +00:00
// fix the clipboard viewer chain
void fixClipboardViewer();
2012-06-10 16:50:54 +00:00
// enable/disable special key combinations so we can catch/pass them
void enableSpecialKeys(bool) const;
2012-06-10 16:50:54 +00:00
// map a button event to a button ID
ButtonID mapButtonFromEvent(WPARAM msg, LPARAM button) const;
2012-06-10 16:50:54 +00:00
// map a button event to a press (true) or release (false)
bool mapPressFromEvent(WPARAM msg, LPARAM button) const;
2012-06-10 16:50:54 +00:00
// job to update the key state
void updateKeysCB(void *);
2012-06-10 16:50:54 +00:00
// determine whether the mouse is hidden by the system.
// if true and on secondary screen, enable mouse keys to show the cursor.
// we were previously restoring the old mouse key settings when not needed, but this was causing
// issues where the mouse cursor becomes permanently hidden, even if there is a real mouse
// attached to the system; this could be a windows bug, but losing your mouse is a nightmare
// so we shouldn't risk doing that.
void setupMouseKeys();
2012-06-10 16:50:54 +00:00
// enables the mouse keys accessibility feature to to ensure the
// mouse cursor can be shown.
void updateMouseKeys();
2012-06-10 16:50:54 +00:00
// our window proc
static LRESULT CALLBACK wndProc(HWND, UINT, WPARAM, LPARAM);
// save last position of mouse to compute next delta movement
2025-01-11 01:11:56 +00:00
void saveMousePosition(int32_t x, int32_t y);
2012-06-10 16:50:54 +00:00
// check if it is a modifier key repeating message
bool isModifierRepeat(KeyModifierMask oldState, KeyModifierMask state, WPARAM wParam) const;
2012-06-10 16:50:54 +00:00
private:
struct HotKeyItem
{
public:
HotKeyItem(UINT vk, UINT modifiers);
UINT getVirtualKey() const;
bool operator<(const HotKeyItem &) const;
private:
UINT m_keycode;
UINT m_mask;
};
2025-01-11 02:13:19 +00:00
using HotKeyMap = std::map<uint32_t, HotKeyItem>;
using HotKeyIDList = std::vector<uint32_t>;
using HotKeyToIDMap = std::map<HotKeyItem, uint32_t>;
using PrimaryKeyDownList = std::vector<KeyButton>;
static HINSTANCE s_windowInstance;
// true if screen is being used as a primary screen, false otherwise
bool m_isPrimary;
// true if hooks are not to be installed (useful for debugging)
bool m_useHooks;
// true if mouse has entered the screen
bool m_isOnScreen;
// true if the screen is enabled
bool m_isEnabled = false;
// our resources
ATOM m_class = 0;
// screen shape stuff
int32_t m_x = 0;
int32_t m_y = 0;
int32_t m_w = 0;
int32_t m_h = 0;
int32_t m_xCenter = 0;
int32_t m_yCenter = 0;
// true if system appears to have multiple monitors
bool m_multimon = false;
// last mouse position
int32_t m_xCursor = 0;
int32_t m_yCursor = 0;
// last clipboard
uint32_t m_sequenceNumber = 0;
// used to discard queued messages that are no longer needed
uint32_t m_mark = 0;
uint32_t m_markReceived = 0;
// the main loop's thread id
DWORD m_threadID;
// timer for periodically checking stuff that requires polling
EventQueueTimer *m_fixTimer = nullptr;
// the keyboard layout to use when off primary screen
HKL m_keyLayout = nullptr;
// screen saver stuff
MSWindowsScreenSaver *m_screensaver = nullptr;
bool m_screensaverNotify = false;
bool m_screensaverActive = false;
// clipboard stuff. our window is used mainly as a clipboard
// owner and as a link in the clipboard viewer chain.
HWND m_window = nullptr;
DWORD m_clipboardSequenceNumber = 0;
bool m_ownClipboard = false;
// one desk per desktop and a cond var to communicate with it
MSWindowsDesks *m_desks = nullptr;
// keyboard stuff
MSWindowsKeyState *m_keyState = nullptr;
// hot key stuff
HotKeyMap m_hotKeys;
HotKeyIDList m_oldHotKeyIDs;
HotKeyToIDMap m_hotKeyToIDMap;
// map of button state
bool m_buttons[1 + kButtonExtra0 + 1];
// m_hasMouse is true if there's a mouse attached to the system or
// mouse keys is simulating one. we track this so we can force the
// cursor to be displayed when the user has entered this screen.
bool m_hasMouse;
bool m_gotMouseKeys = false;
MOUSEKEYS m_mouseKeys;
MSWindowsHook m_hook;
static MSWindowsScreen *s_screen;
IEventQueue *m_events;
std::string m_desktopPath;
PrimaryKeyDownList m_primaryKeyDownList;
MSWindowsPowerManager m_powerManager;
2012-06-10 16:50:54 +00:00
};