1 ////////////////////////////////////////////////////////////
2 //
3 // SFML - Simple and Fast Multimedia Library
4 // Copyright (C) 2007-2018 Laurent Gomila (laurent@sfml-dev.org)
5 //
6 // This software is provided 'as-is', without any express or implied warranty.
7 // In no event will the authors be held liable for any damages arising from the use of this software.
8 //
9 // Permission is granted to anyone to use this software for any purpose,
10 // including commercial applications, and to alter it and redistribute it freely,
11 // subject to the following restrictions:
12 //
13 // 1. The origin of this software must not be misrepresented;
14 //    you must not claim that you wrote the original software.
15 //    If you use this software in a product, an acknowledgment
16 //    in the product documentation would be appreciated but is not required.
17 //
18 // 2. Altered source versions must be plainly marked as such,
19 //    and must not be misrepresented as being the original software.
20 //
21 // 3. This notice may not be removed or altered from any source distribution.
22 //
23 ////////////////////////////////////////////////////////////
24 
25 ////////////////////////////////////////////////////////////
26 // Headers
27 ////////////////////////////////////////////////////////////
28 #include <SFML/Window/Window.hpp> // important to be included first (conflict with None)
29 #include <SFML/Window/Unix/InputImpl.hpp>
30 #include <SFML/Window/Unix/Display.hpp>
31 #include <SFML/System/Err.hpp>
32 #include <X11/Xlib.h>
33 #include <X11/keysym.h>
34 
35 
36 namespace sf
37 {
38 namespace priv
39 {
40 ////////////////////////////////////////////////////////////
isKeyPressed(Keyboard::Key key)41 bool InputImpl::isKeyPressed(Keyboard::Key key)
42 {
43     // Get the corresponding X11 keysym
44     KeySym keysym = 0;
45     switch (key)
46     {
47         case Keyboard::LShift:     keysym = XK_Shift_L;      break;
48         case Keyboard::RShift:     keysym = XK_Shift_R;      break;
49         case Keyboard::LControl:   keysym = XK_Control_L;    break;
50         case Keyboard::RControl:   keysym = XK_Control_R;    break;
51         case Keyboard::LAlt:       keysym = XK_Alt_L;        break;
52         case Keyboard::RAlt:       keysym = XK_Alt_R;        break;
53         case Keyboard::LSystem:    keysym = XK_Super_L;      break;
54         case Keyboard::RSystem:    keysym = XK_Super_R;      break;
55         case Keyboard::Menu:       keysym = XK_Menu;         break;
56         case Keyboard::Escape:     keysym = XK_Escape;       break;
57         case Keyboard::Semicolon:  keysym = XK_semicolon;    break;
58         case Keyboard::Slash:      keysym = XK_slash;        break;
59         case Keyboard::Equal:      keysym = XK_equal;        break;
60         case Keyboard::Hyphen:     keysym = XK_minus;        break;
61         case Keyboard::LBracket:   keysym = XK_bracketleft;  break;
62         case Keyboard::RBracket:   keysym = XK_bracketright; break;
63         case Keyboard::Comma:      keysym = XK_comma;        break;
64         case Keyboard::Period:     keysym = XK_period;       break;
65         case Keyboard::Quote:      keysym = XK_apostrophe;   break;
66         case Keyboard::Backslash:  keysym = XK_backslash;    break;
67         case Keyboard::Tilde:      keysym = XK_grave;        break;
68         case Keyboard::Space:      keysym = XK_space;        break;
69         case Keyboard::Enter:      keysym = XK_Return;       break;
70         case Keyboard::Backspace:  keysym = XK_BackSpace;    break;
71         case Keyboard::Tab:        keysym = XK_Tab;          break;
72         case Keyboard::PageUp:     keysym = XK_Prior;        break;
73         case Keyboard::PageDown:   keysym = XK_Next;         break;
74         case Keyboard::End:        keysym = XK_End;          break;
75         case Keyboard::Home:       keysym = XK_Home;         break;
76         case Keyboard::Insert:     keysym = XK_Insert;       break;
77         case Keyboard::Delete:     keysym = XK_Delete;       break;
78         case Keyboard::Add:        keysym = XK_KP_Add;       break;
79         case Keyboard::Subtract:   keysym = XK_KP_Subtract;  break;
80         case Keyboard::Multiply:   keysym = XK_KP_Multiply;  break;
81         case Keyboard::Divide:     keysym = XK_KP_Divide;    break;
82         case Keyboard::Pause:      keysym = XK_Pause;        break;
83         case Keyboard::F1:         keysym = XK_F1;           break;
84         case Keyboard::F2:         keysym = XK_F2;           break;
85         case Keyboard::F3:         keysym = XK_F3;           break;
86         case Keyboard::F4:         keysym = XK_F4;           break;
87         case Keyboard::F5:         keysym = XK_F5;           break;
88         case Keyboard::F6:         keysym = XK_F6;           break;
89         case Keyboard::F7:         keysym = XK_F7;           break;
90         case Keyboard::F8:         keysym = XK_F8;           break;
91         case Keyboard::F9:         keysym = XK_F9;           break;
92         case Keyboard::F10:        keysym = XK_F10;          break;
93         case Keyboard::F11:        keysym = XK_F11;          break;
94         case Keyboard::F12:        keysym = XK_F12;          break;
95         case Keyboard::F13:        keysym = XK_F13;          break;
96         case Keyboard::F14:        keysym = XK_F14;          break;
97         case Keyboard::F15:        keysym = XK_F15;          break;
98         case Keyboard::Left:       keysym = XK_Left;         break;
99         case Keyboard::Right:      keysym = XK_Right;        break;
100         case Keyboard::Up:         keysym = XK_Up;           break;
101         case Keyboard::Down:       keysym = XK_Down;         break;
102         case Keyboard::Numpad0:    keysym = XK_KP_Insert;    break;
103         case Keyboard::Numpad1:    keysym = XK_KP_End;       break;
104         case Keyboard::Numpad2:    keysym = XK_KP_Down;      break;
105         case Keyboard::Numpad3:    keysym = XK_KP_Page_Down; break;
106         case Keyboard::Numpad4:    keysym = XK_KP_Left;      break;
107         case Keyboard::Numpad5:    keysym = XK_KP_Begin;     break;
108         case Keyboard::Numpad6:    keysym = XK_KP_Right;     break;
109         case Keyboard::Numpad7:    keysym = XK_KP_Home;      break;
110         case Keyboard::Numpad8:    keysym = XK_KP_Up;        break;
111         case Keyboard::Numpad9:    keysym = XK_KP_Page_Up;   break;
112         case Keyboard::A:          keysym = XK_a;            break;
113         case Keyboard::B:          keysym = XK_b;            break;
114         case Keyboard::C:          keysym = XK_c;            break;
115         case Keyboard::D:          keysym = XK_d;            break;
116         case Keyboard::E:          keysym = XK_e;            break;
117         case Keyboard::F:          keysym = XK_f;            break;
118         case Keyboard::G:          keysym = XK_g;            break;
119         case Keyboard::H:          keysym = XK_h;            break;
120         case Keyboard::I:          keysym = XK_i;            break;
121         case Keyboard::J:          keysym = XK_j;            break;
122         case Keyboard::K:          keysym = XK_k;            break;
123         case Keyboard::L:          keysym = XK_l;            break;
124         case Keyboard::M:          keysym = XK_m;            break;
125         case Keyboard::N:          keysym = XK_n;            break;
126         case Keyboard::O:          keysym = XK_o;            break;
127         case Keyboard::P:          keysym = XK_p;            break;
128         case Keyboard::Q:          keysym = XK_q;            break;
129         case Keyboard::R:          keysym = XK_r;            break;
130         case Keyboard::S:          keysym = XK_s;            break;
131         case Keyboard::T:          keysym = XK_t;            break;
132         case Keyboard::U:          keysym = XK_u;            break;
133         case Keyboard::V:          keysym = XK_v;            break;
134         case Keyboard::W:          keysym = XK_w;            break;
135         case Keyboard::X:          keysym = XK_x;            break;
136         case Keyboard::Y:          keysym = XK_y;            break;
137         case Keyboard::Z:          keysym = XK_z;            break;
138         case Keyboard::Num0:       keysym = XK_0;            break;
139         case Keyboard::Num1:       keysym = XK_1;            break;
140         case Keyboard::Num2:       keysym = XK_2;            break;
141         case Keyboard::Num3:       keysym = XK_3;            break;
142         case Keyboard::Num4:       keysym = XK_4;            break;
143         case Keyboard::Num5:       keysym = XK_5;            break;
144         case Keyboard::Num6:       keysym = XK_6;            break;
145         case Keyboard::Num7:       keysym = XK_7;            break;
146         case Keyboard::Num8:       keysym = XK_8;            break;
147         case Keyboard::Num9:       keysym = XK_9;            break;
148         default:                   keysym = 0;               break;
149     }
150 
151     // Sanity checks
152     if (key < 0 || key >= sf::Keyboard::KeyCount)
153         return false;
154 
155     // Open a connection with the X server
156     Display* display = OpenDisplay();
157 
158     // Convert to keycode
159     KeyCode keycode = XKeysymToKeycode(display, keysym);
160     if (keycode != 0)
161     {
162         // Get the whole keyboard state
163         char keys[32];
164         XQueryKeymap(display, keys);
165 
166         // Close the connection with the X server
167         CloseDisplay(display);
168 
169         // Check our keycode
170         return (keys[keycode / 8] & (1 << (keycode % 8))) != 0;
171     }
172     else
173     {
174         // Close the connection with the X server
175         CloseDisplay(display);
176 
177         return false;
178     }
179 }
180 
181 
182 ////////////////////////////////////////////////////////////
setVirtualKeyboardVisible(bool)183 void InputImpl::setVirtualKeyboardVisible(bool /*visible*/)
184 {
185     // Not applicable
186 }
187 
188 
189 ////////////////////////////////////////////////////////////
isMouseButtonPressed(Mouse::Button button)190 bool InputImpl::isMouseButtonPressed(Mouse::Button button)
191 {
192     // Open a connection with the X server
193     Display* display = OpenDisplay();
194 
195     // we don't care about these but they are required
196     ::Window root, child;
197     int wx, wy;
198     int gx, gy;
199 
200     unsigned int buttons = 0;
201     XQueryPointer(display, DefaultRootWindow(display), &root, &child, &gx, &gy, &wx, &wy, &buttons);
202 
203     // Close the connection with the X server
204     CloseDisplay(display);
205 
206     switch (button)
207     {
208         case Mouse::Left:     return buttons & Button1Mask;
209         case Mouse::Right:    return buttons & Button3Mask;
210         case Mouse::Middle:   return buttons & Button2Mask;
211         case Mouse::XButton1: return false; // not supported by X
212         case Mouse::XButton2: return false; // not supported by X
213         default:              return false;
214     }
215 
216     return false;
217 }
218 
219 
220 ////////////////////////////////////////////////////////////
getMousePosition()221 Vector2i InputImpl::getMousePosition()
222 {
223     // Open a connection with the X server
224     Display* display = OpenDisplay();
225 
226     // we don't care about these but they are required
227     ::Window root, child;
228     int x, y;
229     unsigned int buttons;
230 
231     int gx = 0;
232     int gy = 0;
233     XQueryPointer(display, DefaultRootWindow(display), &root, &child, &gx, &gy, &x, &y, &buttons);
234 
235     // Close the connection with the X server
236     CloseDisplay(display);
237 
238     return Vector2i(gx, gy);
239 }
240 
241 
242 ////////////////////////////////////////////////////////////
getMousePosition(const Window & relativeTo)243 Vector2i InputImpl::getMousePosition(const Window& relativeTo)
244 {
245     WindowHandle handle = relativeTo.getSystemHandle();
246     if (handle)
247     {
248         // Open a connection with the X server
249         Display* display = OpenDisplay();
250 
251         // we don't care about these but they are required
252         ::Window root, child;
253         int gx, gy;
254         unsigned int buttons;
255 
256         int x = 0;
257         int y = 0;
258         XQueryPointer(display, handle, &root, &child, &gx, &gy, &x, &y, &buttons);
259 
260         // Close the connection with the X server
261         CloseDisplay(display);
262 
263         return Vector2i(x, y);
264     }
265     else
266     {
267         return Vector2i();
268     }
269 }
270 
271 
272 ////////////////////////////////////////////////////////////
setMousePosition(const Vector2i & position)273 void InputImpl::setMousePosition(const Vector2i& position)
274 {
275     // Open a connection with the X server
276     Display* display = OpenDisplay();
277 
278     XWarpPointer(display, None, DefaultRootWindow(display), 0, 0, 0, 0, position.x, position.y);
279     XFlush(display);
280 
281     // Close the connection with the X server
282     CloseDisplay(display);
283 }
284 
285 
286 ////////////////////////////////////////////////////////////
setMousePosition(const Vector2i & position,const Window & relativeTo)287 void InputImpl::setMousePosition(const Vector2i& position, const Window& relativeTo)
288 {
289     // Open a connection with the X server
290     Display* display = OpenDisplay();
291 
292     WindowHandle handle = relativeTo.getSystemHandle();
293     if (handle)
294     {
295         XWarpPointer(display, None, handle, 0, 0, 0, 0, position.x, position.y);
296         XFlush(display);
297     }
298 
299     // Close the connection with the X server
300     CloseDisplay(display);
301 }
302 
303 
304 ////////////////////////////////////////////////////////////
isTouchDown(unsigned int)305 bool InputImpl::isTouchDown(unsigned int /*finger*/)
306 {
307     // Not applicable
308     return false;
309 }
310 
311 
312 ////////////////////////////////////////////////////////////
getTouchPosition(unsigned int)313 Vector2i InputImpl::getTouchPosition(unsigned int /*finger*/)
314 {
315     // Not applicable
316     return Vector2i();
317 }
318 
319 
320 ////////////////////////////////////////////////////////////
getTouchPosition(unsigned int,const Window &)321 Vector2i InputImpl::getTouchPosition(unsigned int /*finger*/, const Window& /*relativeTo*/)
322 {
323     // Not applicable
324     return Vector2i();
325 }
326 
327 } // namespace priv
328 
329 } // namespace sf
330