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