1 /*
2  * synergy -- mouse and keyboard sharing utility
3  * Copyright (C) 2012-2016 Symless Ltd.
4  * Copyright (C) 2003 Chris Schoeneman
5  *
6  * This package is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU General Public License
8  * found in the file LICENSE that should have accompanied this file.
9  *
10  * This package is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13  * GNU General Public License for more details.
14  *
15  * You should have received a copy of the GNU General Public License
16  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
17  */
18 
19 #pragma once
20 
21 #include "synergy/KeyState.h"
22 #include "common/stdmap.h"
23 #include "common/stdvector.h"
24 
25 #if X_DISPLAY_MISSING
26 #    error X11 is required to build synergy
27 #else
28 #    include <X11/Xlib.h>
29 #    if HAVE_X11_EXTENSIONS_XTEST_H
30 #        include <X11/extensions/XTest.h>
31 #    else
32 #        error The XTest extension is required to build synergy
33 #    endif
34 #    if HAVE_XKB_EXTENSION
35 #        include <X11/extensions/XKBstr.h>
36 #    endif
37 #endif
38 
39 class IEventQueue;
40 
41 //! X Windows key state
42 /*!
43 A key state for X Windows.
44 */
45 class XWindowsKeyState : public KeyState {
46 public:
47     typedef std::vector<int> KeycodeList;
48     enum {
49         kGroupPoll       = -1,
50         kGroupPollAndSet = -2
51     };
52 
53     XWindowsKeyState(Display*, bool useXKB, IEventQueue* events);
54     XWindowsKeyState(Display*, bool useXKB,
55         IEventQueue* events, synergy::KeyMap& keyMap);
56     ~XWindowsKeyState();
57 
58     //! @name modifiers
59     //@{
60 
61     //! Set active group
62     /*!
63     Sets the active group to \p group.  This is the group returned by
64     \c pollActiveGroup().  If \p group is \c kGroupPoll then
65     \c pollActiveGroup() will really poll, but that's a slow operation
66     on X11.  If \p group is \c kGroupPollAndSet then this will poll the
67     active group now and use it for future calls to \c pollActiveGroup().
68     */
69     void                setActiveGroup(SInt32 group);
70 
71     //! Set the auto-repeat state
72     /*!
73     Sets the auto-repeat state.
74     */
75     void                setAutoRepeat(const XKeyboardState&);
76 
77     //@}
78     //! @name accessors
79     //@{
80 
81     //! Convert X modifier mask to synergy mask
82     /*!
83     Returns the synergy modifier mask corresponding to the X modifier
84     mask in \p state.
85     */
86     KeyModifierMask        mapModifiersFromX(unsigned int state) const;
87 
88     //! Convert synergy modifier mask to X mask
89     /*!
90     Converts the synergy modifier mask to the corresponding X modifier
91     mask.  Returns \c true if successful and \c false if any modifier
92     could not be converted.
93     */
94     bool                mapModifiersToX(KeyModifierMask, unsigned int&) const;
95 
96     //! Convert synergy key to all corresponding X keycodes
97     /*!
98     Converts the synergy key \p key to all of the keycodes that map to
99     that key.
100     */
101     void                mapKeyToKeycodes(KeyID key,
102                             KeycodeList& keycodes) const;
103 
104     //@}
105 
106     // IKeyState overrides
107     virtual bool        fakeCtrlAltDel();
108     virtual KeyModifierMask
109                         pollActiveModifiers() const;
110     virtual SInt32        pollActiveGroup() const;
111     virtual void        pollPressedKeys(KeyButtonSet& pressedKeys) const;
112 
113 protected:
114     // KeyState overrides
115     virtual void        getKeyMap(synergy::KeyMap& keyMap);
116     virtual void        fakeKey(const Keystroke& keystroke);
117 
118 private:
119     void                init(Display* display, bool useXKB);
120     void                updateKeysymMap(synergy::KeyMap&);
121     void                updateKeysymMapXKB(synergy::KeyMap&);
122     bool                hasModifiersXKB() const;
123     int                    getEffectiveGroup(KeyCode, int group) const;
124     UInt32                getGroupFromState(unsigned int state) const;
125 
126     static void            remapKeyModifiers(KeyID, SInt32,
127                             synergy::KeyMap::KeyItem&, void*);
128 
129 private:
130     struct XKBModifierInfo {
131     public:
132         unsigned char    m_level;
133         UInt32            m_mask;
134         bool            m_lock;
135     };
136 
137 #ifdef TEST_ENV
138 public: // yuck
139 #endif
140     typedef std::vector<KeyModifierMask> KeyModifierMaskList;
141 
142 private:
143     typedef std::map<KeyModifierMask, unsigned int> KeyModifierToXMask;
144     typedef std::multimap<KeyID, KeyCode> KeyToKeyCodeMap;
145     typedef std::map<KeyCode, unsigned int> NonXKBModifierMap;
146     typedef std::map<UInt32, XKBModifierInfo> XKBModifierMap;
147 
148     Display*            m_display;
149 #if HAVE_XKB_EXTENSION
150     XkbDescPtr            m_xkb;
151 #endif
152     SInt32                m_group;
153     XKBModifierMap        m_lastGoodXKBModifiers;
154     NonXKBModifierMap    m_lastGoodNonXKBModifiers;
155 
156     // X modifier (bit number) to synergy modifier (mask) mapping
157     KeyModifierMaskList    m_modifierFromX;
158 
159     // synergy modifier (mask) to X modifier (mask)
160     KeyModifierToXMask    m_modifierToX;
161 
162     // map KeyID to all keycodes that can synthesize that KeyID
163     KeyToKeyCodeMap        m_keyCodeFromKey;
164 
165     // autorepeat state
166     XKeyboardState        m_keyboardState;
167 
168 #ifdef TEST_ENV
169 public:
group()170     SInt32                  group() const { return m_group; }
group(const SInt32 & group)171     void                    group(const SInt32& group) { m_group = group; }
modifierFromX()172     KeyModifierMaskList    modifierFromX() const { return m_modifierFromX; }
173 #endif
174 };
175