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