/* * synergy -- mouse and keyboard sharing utility * Copyright (C) 2003 Chris Schoeneman * Copyright (C) 2006 Knut St. Osmundsen * * This package is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * found in the file COPYING that should have accompanied this file. * * This package is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. */ #ifndef CPMKEYSTATE_H #define CPMKEYSTATE_H #include "CKeyState.h" #include "CString.h" #include "CPMSynergyHook.h" #include "stdvector.h" #define INCL_ERRORS #define INCL_BASE #define INCL_PM #include class CEvent; class CEventQueueTimer; //! Microsoft Windows key mapper /*! This class maps KeyIDs to keystrokes. */ class CPMKeyState : public CKeyState { public: CPMKeyState(void* eventTarget, FakeMsgFunc fakeMsg); virtual ~CPMKeyState(); //! @name manipulators //@{ //! Handle screen disabling /*! Called when screen is disabled. This is needed to deal with platform brokenness. */ void disable(); //! Test and set autorepeat state /*! Returns true if the given button is autorepeating and updates internal state. */ bool testAutoRepeat(bool press, bool isRepeat, KeyButton); //! Remember modifier state /*! Records the current non-toggle modifier state. */ void saveModifiers(); //! Set effective modifier state /*! Temporarily sets the non-toggle modifier state to those saved by the last call to \c saveModifiers if \p enable is \c true. Restores the modifier state to the current modifier state if \p enable is \c false. This is for synthesizing keystrokes on the primary screen when the cursor is on a secondary screen. When on a secondary screen we capture all non-toggle modifier state, track the state internally and do not pass it on. So if Alt+F1 synthesizes Alt+X we need to synthesize not just X but also Alt, despite the fact that our internal modifier state indicates Alt is down, because local apps never saw the Alt down event. */ void useSavedModifiers(bool enable); //@} //! @name accessors //@{ //! Map a virtual key to a button /*! Returns the button for the \p virtualKey. */ KeyButton virtualKeyToButton(ULONG virtualKey) const; //! Map key event to a key /*! Converts a key event into a KeyID and the shadow modifier state to a modifier mask. */ KeyID mapKeyFromEvent(USHORT fsFlags, UCHAR ucRepeat, UCHAR ucScanCode, USHORT usch, USHORT usvk, KeyModifierMask* maskOut) const; //! Check if keyboard groups have changed /*! Returns true iff the number or order of the keyboard groups have changed since the last call to updateKeys(). */ bool didGroupsChange() const; //! Map key to virtual key /*! Returns the virtual key for key \p key or 0 if there's no such virtual key. */ ULONG mapKeyToVirtualKey(KeyID key) const; //! Map virtual key and button to KeyID /*! Returns the KeyID for virtual key \p virtualKey and button \p button (button should include the extended key bit), or kKeyNone if there is no such key. */ KeyID getKeyID(ULONG virtualKey, KeyButton button, bool fNumPadKey, USHORT usChar); //@} // IKeyState overrides virtual void fakeKeyDown(KeyID id, KeyModifierMask mask, KeyButton button); virtual void fakeKeyRepeat(KeyID id, KeyModifierMask mask, SInt32 count, KeyButton button); virtual bool fakeCtrlAltDel(); virtual KeyModifierMask pollActiveModifiers() const; virtual SInt32 pollActiveGroup() const; virtual void pollPressedKeys(KeyButtonSet& pressedKeys) const; // CKeyState overrides virtual void sendKeyEvent(void* target, bool press, bool isAutoRepeat, KeyID key, KeyModifierMask mask, SInt32 count, KeyButton button); protected: // CKeyState overrides virtual void getKeyMap(CKeyMap& keyMap); virtual void fakeKey(const Keystroke& keystroke); virtual KeyModifierMask& getActiveModifiersRValue(); private: typedef union { /** the 64-bit data view. */ UInt64 u; /** the struct view. */ struct { /** The pm scan code. */ unsigned xlatScan : 8; /** The char. */ unsigned xlatChar: 8; /** The raw scan code. */ unsigned scan : 7; /** KDD_EXTENDEDKEY. */ unsigned fExtendedKey : 1; /** The pm scan code of the 2nd message. */ unsigned xlatScan2 : 8; /** The char of the 2nd message. */ unsigned xlatChar2: 8; /** The raw scan code of the 2nd message. */ unsigned scan2 : 7; /** KDD_SECONDARY. */ unsigned fSecondary : 1; /** The virtual key. */ unsigned virtualKey : 7; /** KC_DEADKEY. */ unsigned fDeadKey : 1; /** KC_COMPOSITE. */ unsigned fComposite : 1; /** shift key. */ unsigned fShiftKey : 1; /** Indicates that the key requires the xlscan=2a KDD_SECONADARY+KDD_UNDEFINED+KDD_UNDEFINED * key if numlock is effective. */ unsigned fNeedNumUnlockKey : 1; /** Bits we haven't used yet. */ unsigned fReserved : 4; } s; } ClientData; void convertScancodes(ClientData *pData); KeyID getIDForKey(CKeyMap::KeyItem& item, KeyButton button, ULONG virtualKey, PBYTE keyState) const; void addKeyEntry(CKeyMap& keyMap, CKeyMap::KeyItem& item); private: // not implemented CPMKeyState(const CPMKeyState&); CPMKeyState& operator=(const CPMKeyState&); private: typedef std::map KeyToVKMap; void* m_eventTarget; ULONG m_buttonToVK[512]; KeyButton m_virtualKeyToButton[256]; KeyToVKMap m_keyToVKMap; // scan code conversions. UInt8 m_pmScanToOemScan[256]; UInt8 m_pmScanToOemScanExt[256]; UInt8 m_oemScanToPmScan[128]; UInt8 m_oemScanToPmScanExt[128]; // function which can inject fake WM_CHAR messages. FakeMsgFunc m_fakeMsg; // the last button pressed. KeyButton m_lastButton; // the timer used to check for fixing key state CEventQueueTimer* m_fixTimer; // the last button that we generated a key down event for. this // is zero if the last key event was a key up. we use this to // synthesize key repeats since the low level keyboard hook can't // tell us if an event is a key repeat. KeyButton m_lastDown; // modifier tracking bool m_useSavedModifiers; KeyModifierMask m_savedModifiers; KeyModifierMask m_originalSavedModifiers; typedef struct { KeyID key; unsigned char ch; bool numpad; char extended; } VirtualKey; static const VirtualKey s_virtualKey[0x42]; }; /* * Local Variables: * mode: c * c-file-style: "k&r" * c-basic-offset: 4 * tab-width: 4 * indent-tabs-mode: t * End: */ #endif