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
5 #ifndef __C_IRR_DEVICE_LINUX_H_INCLUDED__
\r
6 #define __C_IRR_DEVICE_LINUX_H_INCLUDED__
\r
8 #include "IrrCompileConfig.h"
\r
10 #ifdef _IRR_COMPILE_WITH_X11_DEVICE_
\r
12 #include "CIrrDeviceStub.h"
\r
13 #include "IrrlichtDevice.h"
\r
14 #include "ICursorControl.h"
\r
17 #ifdef _IRR_COMPILE_WITH_X11_
\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
24 #ifdef _IRR_LINUX_X11_XINPUT2_
\r
25 #include <X11/extensions/XInput2.h>
\r
35 class CIrrDeviceLinux : public CIrrDeviceStub
\r
40 CIrrDeviceLinux(const SIrrlichtCreationParameters& param);
\r
43 virtual ~CIrrDeviceLinux();
\r
45 //! runs the device. Returns false if device wants to be deleted
\r
46 bool run() override;
\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
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
55 //! sets the caption of the window
\r
56 void setWindowCaption(const wchar_t* text) override;
\r
58 //! returns if window is active. if not, nothing need to be drawn
\r
59 bool isWindowActive() const override;
\r
61 //! returns if window has focus.
\r
62 bool isWindowFocused() const override;
\r
64 //! returns if window is minimized.
\r
65 bool isWindowMinimized() const override;
\r
67 //! returns last state from maximizeWindow() and restoreWindow()
\r
68 bool isWindowMaximized() const override;
\r
70 //! returns color format of the window.
\r
71 video::ECOLOR_FORMAT getColorFormat() const override;
\r
73 //! notifies the device that it should close itself
\r
74 void closeDevice() override;
\r
76 //! Sets if the window should be resizable in windowed mode.
\r
77 void setResizable(bool resize=false) override;
\r
79 //! Resize the render window.
\r
80 void setWindowSize(const irr::core::dimension2d<u32>& size) override;
\r
82 //! Minimizes the window.
\r
83 void minimizeWindow() override;
\r
85 //! Maximizes the window.
\r
86 void maximizeWindow() override;
\r
88 //! Restores the window size.
\r
89 void restoreWindow() override;
\r
91 //! Get the position of this window on screen
\r
92 core::position2di getWindowPosition() override;
\r
94 //! Activate any joysticks, and generate events for them.
\r
95 bool activateJoysticks(core::array<SJoystickInfo> & joystickInfo) override;
\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
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
106 //! Remove all messages pending in the system message loop
\r
107 void clearSystemMessages() override;
\r
109 //! Get the device type
\r
110 E_DEVICE_TYPE getType() const override
\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
126 //! create the driver
\r
127 void createDriver();
\r
129 bool createWindow();
\r
131 void createKeyMap();
\r
133 void pollJoysticks();
\r
137 void initXInput2();
\r
139 bool switchToFullscreen();
\r
141 #ifdef _IRR_COMPILE_WITH_X11_
\r
142 bool createInputContext();
\r
143 void destroyInputContext();
\r
144 EKEY_CODE getKeyCode(XEvent &event);
\r
147 //! Implementation of the linux cursor control
\r
148 class CCursorControl : public gui::ICursorControl
\r
152 CCursorControl(CIrrDeviceLinux* dev, bool null);
\r
156 //! Changes the visible state of the mouse cursor.
\r
157 void setVisible(bool visible) override
\r
159 if (visible==IsVisible)
\r
161 IsVisible = visible;
\r
162 #ifdef _IRR_COMPILE_WITH_X11_
\r
166 XDefineCursor( Device->XDisplay, Device->XWindow, InvisCursor );
\r
168 XUndefineCursor( Device->XDisplay, Device->XWindow );
\r
173 //! Returns if the cursor is currently visible.
\r
174 bool isVisible() const override
\r
179 //! Sets the new position of the cursor.
\r
180 void setPosition(const core::position2d<f32> &pos) override
\r
182 setPosition(pos.X, pos.Y);
\r
185 //! Sets the new position of the cursor.
\r
186 void setPosition(f32 x, f32 y) override
\r
188 setPosition((s32)(x*Device->Width), (s32)(y*Device->Height));
\r
191 //! Sets the new position of the cursor.
\r
192 void setPosition(const core::position2d<s32> &pos) override
\r
194 setPosition(pos.X, pos.Y);
\r
197 //! Sets the new position of the cursor.
\r
198 void setPosition(s32 x, s32 y) override
\r
200 #ifdef _IRR_COMPILE_WITH_X11_
\r
204 if (UseReferenceRect)
\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
212 XIWarpPointer(Device->XDisplay,
\r
215 Device->XWindow, 0, 0,
\r
218 ReferenceRect.UpperLeftCorner.X + x,
\r
219 ReferenceRect.UpperLeftCorner.Y + y);
\r
224 XWarpPointer(Device->XDisplay,
\r
226 Device->XWindow, 0, 0,
\r
229 ReferenceRect.UpperLeftCorner.X + x,
\r
230 ReferenceRect.UpperLeftCorner.Y + y);
\r
235 #ifdef _IRR_LINUX_X11_XINPUT2_
\r
236 if ( DeviceId != 0)
\r
238 XIWarpPointer(Device->XDisplay,
\r
241 Device->XWindow, 0, 0,
\r
243 Device->Height, x, y);
\r
248 XWarpPointer(Device->XDisplay,
\r
250 Device->XWindow, 0, 0,
\r
252 Device->Height, x, y);
\r
255 XFlush(Device->XDisplay);
\r
262 //! Returns the current position of the mouse cursor.
\r
263 const core::position2d<s32>& getPosition(bool updateCursor) override
\r
265 if ( updateCursor )
\r
270 //! Returns the current position of the mouse cursor.
\r
271 core::position2d<f32> getRelativePosition(bool updateCursor) override
\r
273 if ( updateCursor )
\r
276 if (!UseReferenceRect)
\r
278 return core::position2d<f32>(CursorPos.X / (f32)Device->Width,
\r
279 CursorPos.Y / (f32)Device->Height);
\r
282 return core::position2d<f32>(CursorPos.X / (f32)ReferenceRect.getWidth(),
\r
283 CursorPos.Y / (f32)ReferenceRect.getHeight());
\r
286 void setReferenceRect(core::rect<s32>* rect=0) override
\r
290 ReferenceRect = *rect;
\r
291 UseReferenceRect = true;
\r
293 // prevent division through zero and uneven sizes
\r
295 if (!ReferenceRect.getHeight() || ReferenceRect.getHeight()%2)
\r
296 ReferenceRect.LowerRightCorner.Y += 1;
\r
298 if (!ReferenceRect.getWidth() || ReferenceRect.getWidth()%2)
\r
299 ReferenceRect.LowerRightCorner.X += 1;
\r
302 UseReferenceRect = false;
\r
305 //! Sets the active cursor icon
\r
306 void setActiveIcon(gui::ECURSOR_ICON iconId) override;
\r
308 //! Gets the currently active icon
\r
309 gui::ECURSOR_ICON getActiveIcon() const override
\r
314 //! Add a custom sprite as cursor icon.
\r
315 gui::ECURSOR_ICON addIcon(const gui::SCursorSprite& icon) override;
\r
317 //! replace the given cursor icon.
\r
318 void changeIcon(gui::ECURSOR_ICON iconId, const gui::SCursorSprite& icon) override;
\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
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
327 //! Return platform specific behavior.
\r
328 gui::ECURSOR_PLATFORM_BEHAVIOR getPlatformBehavior() const override { return PlatformBehavior; }
\r
331 void clearCursors();
\r
335 void updateCursorPos()
\r
337 #ifdef _IRR_COMPILE_WITH_X11_
\r
341 if ( PlatformBehavior&gui::ECPB_X11_CACHE_UPDATES && !os::Timer::isStopped() )
\r
343 u32 now = os::Timer::getTime();
\r
344 if (now <= LastQuery)
\r
351 unsigned int maskreturn;
\r
352 XQueryPointer(Device->XDisplay, Device->XWindow,
\r
355 &CursorPos.X, &CursorPos.Y, &maskreturn);
\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
365 Cursor InvisCursor;
\r
367 #ifdef _IRR_LINUX_X11_XINPUT2_
\r
371 struct CursorFrameX11
\r
373 CursorFrameX11() : IconHW(0) {}
\r
374 CursorFrameX11(Cursor icon) : IconHW(icon) {}
\r
376 Cursor IconHW; // hardware cursor
\r
382 explicit CursorX11(Cursor iconHw, u32 frameTime=0) : FrameTime(frameTime)
\r
384 Frames.push_back( CursorFrameX11(iconHw) );
\r
386 core::array<CursorFrameX11> Frames;
\r
390 core::array<CursorX11> Cursors;
\r
392 void initCursors();
\r
396 bool UseReferenceRect;
\r
397 gui::ECURSOR_ICON ActiveIcon;
\r
398 u32 ActiveIconStartTime;
\r
401 friend class CCursorControl;
\r
403 #ifdef _IRR_COMPILE_WITH_X11_
\r
404 friend class COpenGLDriver;
\r
407 XVisualInfo* VisualInfo;
\r
410 XSetWindowAttributes WndAttributes;
\r
411 XSizeHints* StdHints;
\r
416 mutable core::stringc Clipboard;
\r
419 bool WindowHasFocus;
\r
420 bool WindowMinimized;
\r
421 bool WindowMaximized;
\r
422 bool ExternalWindow;
\r
423 int AutorepeatSupport;
\r
428 SKeyMap(s32 x11, s32 win32)
\r
429 : X11Key(x11), Win32Key(win32)
\r
436 bool operator<(const SKeyMap& o) const
\r
438 return X11Key<o.X11Key;
\r
442 core::array<SKeyMap> KeyMap;
\r
444 #if defined(_IRR_COMPILE_WITH_JOYSTICK_EVENTS_)
\r
445 struct JoystickInfo
\r
451 SEvent persistentData;
\r
453 JoystickInfo() : fd(-1), axes(0), buttons(0) { }
\r
455 core::array<JoystickInfo> ActiveJoysticks;
\r
458 #if defined(_IRR_LINUX_X11_XINPUT2_)
\r
459 int currentTouchedCount;
\r
464 } // end namespace irr
\r
466 #endif // _IRR_COMPILE_WITH_X11_DEVICE_
\r
467 #endif // __C_IRR_DEVICE_LINUX_H_INCLUDED__
\r