]> git.lizzy.rs Git - irrlicht.git/blob - source/Irrlicht/CIrrDeviceLinux.h
Merge branch 'master' into opengl3
[irrlicht.git] / source / Irrlicht / CIrrDeviceLinux.h
1 // Copyright (C) 2002-2012 Nikolaus Gebhardt\r
2 // This file is part of the "Irrlicht Engine".\r
3 // For conditions of distribution and use, see copyright notice in irrlicht.h\r
4 \r
5 #ifndef __C_IRR_DEVICE_LINUX_H_INCLUDED__\r
6 #define __C_IRR_DEVICE_LINUX_H_INCLUDED__\r
7 \r
8 \r
9 #ifdef _IRR_COMPILE_WITH_X11_DEVICE_\r
10 \r
11 #include "CIrrDeviceStub.h"\r
12 #include "IrrlichtDevice.h"\r
13 #include "ICursorControl.h"\r
14 #include "os.h"\r
15 \r
16 #ifdef _IRR_COMPILE_WITH_X11_\r
17 \r
18 #include <X11/Xlib.h>\r
19 #include <X11/Xutil.h>\r
20 #include <X11/cursorfont.h>\r
21 #include <X11/keysym.h>\r
22 \r
23 #ifdef _IRR_LINUX_X11_XINPUT2_\r
24 #include <X11/extensions/XInput2.h>\r
25 #endif\r
26 \r
27 #else\r
28 #define KeySym s32\r
29 #endif\r
30 \r
31 namespace irr\r
32 {\r
33 \r
34         class CIrrDeviceLinux : public CIrrDeviceStub\r
35         {\r
36         public:\r
37 \r
38                 //! constructor\r
39                 CIrrDeviceLinux(const SIrrlichtCreationParameters& param);\r
40 \r
41                 //! destructor\r
42                 virtual ~CIrrDeviceLinux();\r
43 \r
44                 //! runs the device. Returns false if device wants to be deleted\r
45                 bool run() override;\r
46 \r
47                 //! Cause the device to temporarily pause execution and let other processes to run\r
48                 // This should bring down processor usage without major performance loss for Irrlicht\r
49                 void yield() override;\r
50 \r
51                 //! Pause execution and let other processes to run for a specified amount of time.\r
52                 void sleep(u32 timeMs, bool pauseTimer) override;\r
53 \r
54                 //! sets the caption of the window\r
55                 void setWindowCaption(const wchar_t* text) override;\r
56 \r
57                 //! returns if window is active. if not, nothing need to be drawn\r
58                 bool isWindowActive() const override;\r
59 \r
60                 //! returns if window has focus.\r
61                 bool isWindowFocused() const override;\r
62 \r
63                 //! returns if window is minimized.\r
64                 bool isWindowMinimized() const override;\r
65 \r
66                 //! returns last state from maximizeWindow() and restoreWindow()\r
67                 bool isWindowMaximized() const override;\r
68 \r
69                 //! returns color format of the window.\r
70                 video::ECOLOR_FORMAT getColorFormat() const override;\r
71 \r
72                 //! notifies the device that it should close itself\r
73                 void closeDevice() override;\r
74 \r
75                 //! Sets if the window should be resizable in windowed mode.\r
76                 void setResizable(bool resize=false) override;\r
77 \r
78                 //! Resize the render window.\r
79                 void setWindowSize(const irr::core::dimension2d<u32>& size) override;\r
80 \r
81                 //! Minimizes the window.\r
82                 void minimizeWindow() override;\r
83 \r
84                 //! Maximizes the window.\r
85                 void maximizeWindow() override;\r
86 \r
87                 //! Restores the window size.\r
88                 void restoreWindow() override;\r
89 \r
90                 //! Get the position of this window on screen\r
91                 core::position2di getWindowPosition() override;\r
92 \r
93                 //! Activate any joysticks, and generate events for them.\r
94                 bool activateJoysticks(core::array<SJoystickInfo> & joystickInfo) override;\r
95 \r
96                 //! gets text from the clipboard\r
97                 //! \return Returns 0 if no string is in there, otherwise utf-8 text.\r
98                 virtual const c8 *getTextFromClipboard() const;\r
99 \r
100                 //! copies text to the clipboard\r
101                 //! This sets the clipboard selection and _not_ the primary selection which you have on X on the middle mouse button.\r
102                 //! @param text The text in utf-8\r
103                 virtual void copyToClipboard(const c8 *text) const;\r
104 \r
105                 //! Remove all messages pending in the system message loop\r
106                 void clearSystemMessages() override;\r
107 \r
108                 //! Get the device type\r
109                 E_DEVICE_TYPE getType() const override\r
110                 {\r
111                         return EIDT_X11;\r
112                 }\r
113 \r
114 #ifdef _IRR_COMPILE_WITH_X11_\r
115                 // convert an Irrlicht texture to a X11 cursor\r
116                 Cursor TextureToCursor(irr::video::ITexture * tex, const core::rect<s32>& sourceRect, const core::position2d<s32> &hotspot);\r
117                 Cursor TextureToMonochromeCursor(irr::video::ITexture * tex, const core::rect<s32>& sourceRect, const core::position2d<s32> &hotspot);\r
118 #ifdef _IRR_LINUX_XCURSOR_\r
119                 Cursor TextureToARGBCursor(irr::video::ITexture * tex, const core::rect<s32>& sourceRect, const core::position2d<s32> &hotspot);\r
120 #endif\r
121 #endif\r
122 \r
123         private:\r
124 \r
125                 //! create the driver\r
126                 void createDriver();\r
127 \r
128                 bool createWindow();\r
129 \r
130                 void createKeyMap();\r
131 \r
132                 void pollJoysticks();\r
133 \r
134                 void initXAtoms();\r
135 \r
136                 void initXInput2();\r
137 \r
138                 bool switchToFullscreen();\r
139 \r
140 #ifdef _IRR_COMPILE_WITH_X11_\r
141                 bool createInputContext();\r
142                 void destroyInputContext();\r
143                 EKEY_CODE getKeyCode(XEvent &event);\r
144 #endif\r
145 \r
146                 //! Implementation of the linux cursor control\r
147                 class CCursorControl : public gui::ICursorControl\r
148                 {\r
149                 public:\r
150 \r
151                         CCursorControl(CIrrDeviceLinux* dev, bool null);\r
152 \r
153                         ~CCursorControl();\r
154 \r
155                         //! Changes the visible state of the mouse cursor.\r
156                         void setVisible(bool visible) override\r
157                         {\r
158                                 if (visible==IsVisible)\r
159                                         return;\r
160                                 IsVisible = visible;\r
161 #ifdef _IRR_COMPILE_WITH_X11_\r
162                                 if (!Null)\r
163                                 {\r
164                                         if ( !IsVisible )\r
165                                                 XDefineCursor( Device->XDisplay, Device->XWindow, InvisCursor );\r
166                                         else\r
167                                                 XUndefineCursor( Device->XDisplay, Device->XWindow );\r
168                                 }\r
169 #endif\r
170                         }\r
171 \r
172                         //! Returns if the cursor is currently visible.\r
173                         bool isVisible() const override\r
174                         {\r
175                                 return IsVisible;\r
176                         }\r
177 \r
178                         //! Sets the new position of the cursor.\r
179                         void setPosition(const core::position2d<f32> &pos) override\r
180                         {\r
181                                 setPosition(pos.X, pos.Y);\r
182                         }\r
183 \r
184                         //! Sets the new position of the cursor.\r
185                         void setPosition(f32 x, f32 y) override\r
186                         {\r
187                                 setPosition((s32)(x*Device->Width), (s32)(y*Device->Height));\r
188                         }\r
189 \r
190                         //! Sets the new position of the cursor.\r
191                         void setPosition(const core::position2d<s32> &pos) override\r
192                         {\r
193                                 setPosition(pos.X, pos.Y);\r
194                         }\r
195 \r
196                         //! Sets the new position of the cursor.\r
197                         void setPosition(s32 x, s32 y) override\r
198                         {\r
199 #ifdef _IRR_COMPILE_WITH_X11_\r
200 \r
201                                 if (!Null)\r
202                                 {\r
203                                         if (UseReferenceRect)\r
204                                         {\r
205 // NOTE: XIWarpPointer works when X11 has set a coordinate transformation matrix for the mouse unlike XWarpPointer\r
206 // which runs into a bug mentioned here: https://gitlab.freedesktop.org/xorg/xserver/-/issues/600\r
207 // So also workaround for Irrlicht bug #450\r
208 #ifdef _IRR_LINUX_X11_XINPUT2_\r
209                                                 if ( DeviceId != 0)\r
210                                                 {\r
211                                                         XIWarpPointer(Device->XDisplay,\r
212                                                                 DeviceId,\r
213                                                                 None,\r
214                                                                 Device->XWindow, 0, 0,\r
215                                                                 Device->Width,\r
216                                                                 Device->Height,\r
217                                                                 ReferenceRect.UpperLeftCorner.X + x,\r
218                                                                 ReferenceRect.UpperLeftCorner.Y + y);\r
219                                                 }\r
220                                                 else\r
221 #endif\r
222                                                 {\r
223                                                         XWarpPointer(Device->XDisplay,\r
224                                                                 None,\r
225                                                                 Device->XWindow, 0, 0,\r
226                                                                 Device->Width,\r
227                                                                 Device->Height,\r
228                                                                 ReferenceRect.UpperLeftCorner.X + x,\r
229                                                                 ReferenceRect.UpperLeftCorner.Y + y);\r
230                                                 }\r
231                                         }\r
232                                         else\r
233                                         {\r
234 #ifdef _IRR_LINUX_X11_XINPUT2_\r
235                                                 if ( DeviceId != 0)\r
236                                                 {\r
237                                                         XIWarpPointer(Device->XDisplay,\r
238                                                                 DeviceId,\r
239                                                                 None,\r
240                                                                 Device->XWindow, 0, 0,\r
241                                                                 Device->Width,\r
242                                                                 Device->Height, x, y);\r
243                                                 }\r
244                                                 else\r
245 #endif\r
246                                                 {\r
247                                                         XWarpPointer(Device->XDisplay,\r
248                                                                 None,\r
249                                                                 Device->XWindow, 0, 0,\r
250                                                                 Device->Width,\r
251                                                                 Device->Height, x, y);\r
252                                                 }\r
253                                         }\r
254                                         XFlush(Device->XDisplay);\r
255                                 }\r
256 #endif\r
257                                 CursorPos.X = x;\r
258                                 CursorPos.Y = y;\r
259                         }\r
260 \r
261                         //! Returns the current position of the mouse cursor.\r
262                         const core::position2d<s32>& getPosition(bool updateCursor) override\r
263                         {\r
264                                 if ( updateCursor )\r
265                                         updateCursorPos();\r
266                                 return CursorPos;\r
267                         }\r
268 \r
269                         //! Returns the current position of the mouse cursor.\r
270                         core::position2d<f32> getRelativePosition(bool updateCursor) override\r
271                         {\r
272                                 if ( updateCursor )\r
273                                         updateCursorPos();\r
274 \r
275                                 if (!UseReferenceRect)\r
276                                 {\r
277                                         return core::position2d<f32>(CursorPos.X / (f32)Device->Width,\r
278                                                 CursorPos.Y / (f32)Device->Height);\r
279                                 }\r
280 \r
281                                 return core::position2d<f32>(CursorPos.X / (f32)ReferenceRect.getWidth(),\r
282                                                 CursorPos.Y / (f32)ReferenceRect.getHeight());\r
283                         }\r
284 \r
285                         void setReferenceRect(core::rect<s32>* rect=0) override\r
286                         {\r
287                                 if (rect)\r
288                                 {\r
289                                         ReferenceRect = *rect;\r
290                                         UseReferenceRect = true;\r
291 \r
292                                         // prevent division through zero and uneven sizes\r
293 \r
294                                         if (!ReferenceRect.getHeight() || ReferenceRect.getHeight()%2)\r
295                                                 ReferenceRect.LowerRightCorner.Y += 1;\r
296 \r
297                                         if (!ReferenceRect.getWidth() || ReferenceRect.getWidth()%2)\r
298                                                 ReferenceRect.LowerRightCorner.X += 1;\r
299                                 }\r
300                                 else\r
301                                         UseReferenceRect = false;\r
302                         }\r
303 \r
304                         //! Sets the active cursor icon\r
305                         void setActiveIcon(gui::ECURSOR_ICON iconId) override;\r
306 \r
307                         //! Gets the currently active icon\r
308                         gui::ECURSOR_ICON getActiveIcon() const override\r
309                         {\r
310                                 return ActiveIcon;\r
311                         }\r
312 \r
313                         //! Add a custom sprite as cursor icon.\r
314                         gui::ECURSOR_ICON addIcon(const gui::SCursorSprite& icon) override;\r
315 \r
316                         //! replace the given cursor icon.\r
317                         void changeIcon(gui::ECURSOR_ICON iconId, const gui::SCursorSprite& icon) override;\r
318 \r
319                         //! Return a system-specific size which is supported for cursors. Larger icons will fail, smaller icons might work.\r
320                         core::dimension2di getSupportedIconSize() const override;\r
321 \r
322 #ifdef _IRR_COMPILE_WITH_X11_\r
323                         //! Set platform specific behavior flags.\r
324                         void setPlatformBehavior(gui::ECURSOR_PLATFORM_BEHAVIOR behavior) override {PlatformBehavior = behavior; }\r
325 \r
326                         //! Return platform specific behavior.\r
327                         gui::ECURSOR_PLATFORM_BEHAVIOR getPlatformBehavior() const override { return PlatformBehavior; }\r
328 \r
329                         void update();\r
330                         void clearCursors();\r
331 #endif\r
332                 private:\r
333 \r
334                         void updateCursorPos()\r
335                         {\r
336 #ifdef _IRR_COMPILE_WITH_X11_\r
337                                 if (Null)\r
338                                         return;\r
339 \r
340                                 if ( PlatformBehavior&gui::ECPB_X11_CACHE_UPDATES && !os::Timer::isStopped() )\r
341                                 {\r
342                                         u32 now = os::Timer::getTime();\r
343                                         if (now <= LastQuery)\r
344                                                 return;\r
345                                         LastQuery = now;\r
346                                 }\r
347 \r
348                                 Window tmp;\r
349                                 int itmp1, itmp2;\r
350                                 unsigned  int maskreturn;\r
351                                 XQueryPointer(Device->XDisplay, Device->XWindow,\r
352                                         &tmp, &tmp,\r
353                                         &itmp1, &itmp2,\r
354                                         &CursorPos.X, &CursorPos.Y, &maskreturn);\r
355 #endif\r
356                         }\r
357 \r
358                         CIrrDeviceLinux* Device;\r
359                         core::position2d<s32> CursorPos;\r
360                         core::rect<s32> ReferenceRect;\r
361 #ifdef _IRR_COMPILE_WITH_X11_\r
362                         gui::ECURSOR_PLATFORM_BEHAVIOR PlatformBehavior;\r
363                         u32 LastQuery;\r
364                         Cursor InvisCursor;\r
365 \r
366 #ifdef _IRR_LINUX_X11_XINPUT2_\r
367                         int DeviceId;\r
368 #endif\r
369 \r
370                         struct CursorFrameX11\r
371                         {\r
372                                 CursorFrameX11() : IconHW(0) {}\r
373                                 CursorFrameX11(Cursor icon) : IconHW(icon) {}\r
374 \r
375                                 Cursor IconHW;  // hardware cursor\r
376                         };\r
377 \r
378                         struct CursorX11\r
379                         {\r
380                                 CursorX11() {}\r
381                                 explicit CursorX11(Cursor iconHw, u32 frameTime=0) : FrameTime(frameTime)\r
382                                 {\r
383                                         Frames.push_back( CursorFrameX11(iconHw) );\r
384                                 }\r
385                                 core::array<CursorFrameX11> Frames;\r
386                                 u32 FrameTime;\r
387                         };\r
388 \r
389                         core::array<CursorX11> Cursors;\r
390 \r
391                         void initCursors();\r
392 #endif\r
393                         bool IsVisible;\r
394                         bool Null;\r
395                         bool UseReferenceRect;\r
396                         gui::ECURSOR_ICON ActiveIcon;\r
397                         u32 ActiveIconStartTime;\r
398                 };\r
399 \r
400                 friend class CCursorControl;\r
401 \r
402 #ifdef _IRR_COMPILE_WITH_X11_\r
403                 friend class COpenGLDriver;\r
404 \r
405                 Display *XDisplay;\r
406                 XVisualInfo* VisualInfo;\r
407                 int Screennr;\r
408                 Window XWindow;\r
409                 XSetWindowAttributes WndAttributes;\r
410                 XSizeHints* StdHints;\r
411                 XIM XInputMethod;\r
412                 XIC XInputContext;\r
413                 bool HasNetWM;\r
414                 // text is utf-8\r
415                 mutable core::stringc Clipboard;\r
416 #endif\r
417 #if defined(_IRR_LINUX_X11_XINPUT2_)\r
418                 int currentTouchedCount;\r
419 #endif\r
420                 u32 Width, Height;\r
421                 bool WindowHasFocus;\r
422                 bool WindowMinimized;\r
423                 bool WindowMaximized;\r
424                 bool ExternalWindow;\r
425                 int AutorepeatSupport;\r
426 \r
427                 struct SKeyMap\r
428                 {\r
429                         SKeyMap() {}\r
430                         SKeyMap(s32 x11, s32 win32)\r
431                                 : X11Key(x11), Win32Key(win32)\r
432                         {\r
433                         }\r
434 \r
435                         KeySym X11Key;\r
436                         s32 Win32Key;\r
437 \r
438                         bool operator<(const SKeyMap& o) const\r
439                         {\r
440                                 return X11Key<o.X11Key;\r
441                         }\r
442                 };\r
443 \r
444                 core::array<SKeyMap> KeyMap;\r
445 \r
446 #if defined(_IRR_COMPILE_WITH_JOYSTICK_EVENTS_)\r
447                 struct JoystickInfo\r
448                 {\r
449                         int     fd;\r
450                         int     axes;\r
451                         int     buttons;\r
452 \r
453                         SEvent persistentData;\r
454 \r
455                         JoystickInfo() : fd(-1), axes(0), buttons(0) { }\r
456                 };\r
457                 core::array<JoystickInfo> ActiveJoysticks;\r
458 #endif\r
459         };\r
460 \r
461 \r
462 } // end namespace irr\r
463 \r
464 #endif // _IRR_COMPILE_WITH_X11_DEVICE_\r
465 #endif // __C_IRR_DEVICE_LINUX_H_INCLUDED__\r
466 \r