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
9 #ifdef _IRR_COMPILE_WITH_X11_DEVICE_
\r
11 #include "CIrrDeviceStub.h"
\r
12 #include "IrrlichtDevice.h"
\r
13 #include "ICursorControl.h"
\r
16 #ifdef _IRR_COMPILE_WITH_X11_
\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
23 #ifdef _IRR_LINUX_X11_XINPUT2_
\r
24 #include <X11/extensions/XInput2.h>
\r
34 class CIrrDeviceLinux : public CIrrDeviceStub
\r
39 CIrrDeviceLinux(const SIrrlichtCreationParameters& param);
\r
42 virtual ~CIrrDeviceLinux();
\r
44 //! runs the device. Returns false if device wants to be deleted
\r
45 bool run() override;
\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
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
54 //! sets the caption of the window
\r
55 void setWindowCaption(const wchar_t* text) override;
\r
57 //! returns if window is active. if not, nothing need to be drawn
\r
58 bool isWindowActive() const override;
\r
60 //! returns if window has focus.
\r
61 bool isWindowFocused() const override;
\r
63 //! returns if window is minimized.
\r
64 bool isWindowMinimized() const override;
\r
66 //! returns last state from maximizeWindow() and restoreWindow()
\r
67 bool isWindowMaximized() const override;
\r
69 //! returns color format of the window.
\r
70 video::ECOLOR_FORMAT getColorFormat() const override;
\r
72 //! notifies the device that it should close itself
\r
73 void closeDevice() override;
\r
75 //! Sets if the window should be resizable in windowed mode.
\r
76 void setResizable(bool resize=false) override;
\r
78 //! Resize the render window.
\r
79 void setWindowSize(const irr::core::dimension2d<u32>& size) override;
\r
81 //! Minimizes the window.
\r
82 void minimizeWindow() override;
\r
84 //! Maximizes the window.
\r
85 void maximizeWindow() override;
\r
87 //! Restores the window size.
\r
88 void restoreWindow() override;
\r
90 //! Get the position of this window on screen
\r
91 core::position2di getWindowPosition() override;
\r
93 //! Activate any joysticks, and generate events for them.
\r
94 bool activateJoysticks(core::array<SJoystickInfo> & joystickInfo) override;
\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
100 //! gets text from the primary selection
\r
101 //! \return Returns 0 if no string is in there, otherwise utf-8 text.
\r
102 virtual const c8 *getTextFromPrimarySelection() const;
\r
104 //! copies text to the clipboard
\r
105 //! This sets the clipboard selection and _not_ the primary selection.
\r
106 //! @param text The text in utf-8
\r
107 virtual void copyToClipboard(const c8 *text) const;
\r
109 //! copies text to the primary selection
\r
110 //! This sets the primary selection which you have on X on the middle mouse button.
\r
111 //! @param text The text in utf-8
\r
112 virtual void copyToPrimarySelection(const c8 *text) const;
\r
114 //! Remove all messages pending in the system message loop
\r
115 void clearSystemMessages() override;
\r
117 //! Get the device type
\r
118 E_DEVICE_TYPE getType() const override
\r
123 #ifdef _IRR_COMPILE_WITH_X11_
\r
124 // convert an Irrlicht texture to a X11 cursor
\r
125 Cursor TextureToCursor(irr::video::ITexture * tex, const core::rect<s32>& sourceRect, const core::position2d<s32> &hotspot);
\r
126 Cursor TextureToMonochromeCursor(irr::video::ITexture * tex, const core::rect<s32>& sourceRect, const core::position2d<s32> &hotspot);
\r
127 #ifdef _IRR_LINUX_XCURSOR_
\r
128 Cursor TextureToARGBCursor(irr::video::ITexture * tex, const core::rect<s32>& sourceRect, const core::position2d<s32> &hotspot);
\r
134 //! create the driver
\r
135 void createDriver();
\r
137 bool createWindow();
\r
139 void createKeyMap();
\r
141 void pollJoysticks();
\r
145 void initXInput2();
\r
147 bool switchToFullscreen();
\r
149 #ifdef _IRR_COMPILE_WITH_X11_
\r
150 bool createInputContext();
\r
151 void destroyInputContext();
\r
152 EKEY_CODE getKeyCode(XEvent &event);
\r
154 const c8 *getTextFromSelection(Atom selection, core::stringc &text_buffer) const;
\r
155 bool becomeSelectionOwner(Atom selection) const;
\r
158 //! Implementation of the linux cursor control
\r
159 class CCursorControl : public gui::ICursorControl
\r
163 CCursorControl(CIrrDeviceLinux* dev, bool null);
\r
167 //! Changes the visible state of the mouse cursor.
\r
168 void setVisible(bool visible) override
\r
170 if (visible==IsVisible)
\r
172 IsVisible = visible;
\r
173 #ifdef _IRR_COMPILE_WITH_X11_
\r
177 XDefineCursor( Device->XDisplay, Device->XWindow, InvisCursor );
\r
179 XUndefineCursor( Device->XDisplay, Device->XWindow );
\r
184 //! Returns if the cursor is currently visible.
\r
185 bool isVisible() const override
\r
190 //! Sets the new position of the cursor.
\r
191 void setPosition(const core::position2d<f32> &pos) override
\r
193 setPosition(pos.X, pos.Y);
\r
196 //! Sets the new position of the cursor.
\r
197 void setPosition(f32 x, f32 y) override
\r
199 setPosition((s32)(x*Device->Width), (s32)(y*Device->Height));
\r
202 //! Sets the new position of the cursor.
\r
203 void setPosition(const core::position2d<s32> &pos) override
\r
205 setPosition(pos.X, pos.Y);
\r
208 //! Sets the new position of the cursor.
\r
209 void setPosition(s32 x, s32 y) override
\r
211 #ifdef _IRR_COMPILE_WITH_X11_
\r
215 if (UseReferenceRect)
\r
217 // NOTE: XIWarpPointer works when X11 has set a coordinate transformation matrix for the mouse unlike XWarpPointer
\r
218 // which runs into a bug mentioned here: https://gitlab.freedesktop.org/xorg/xserver/-/issues/600
\r
219 // So also workaround for Irrlicht bug #450
\r
220 #ifdef _IRR_LINUX_X11_XINPUT2_
\r
221 if ( DeviceId != 0)
\r
223 XIWarpPointer(Device->XDisplay,
\r
226 Device->XWindow, 0, 0,
\r
229 ReferenceRect.UpperLeftCorner.X + x,
\r
230 ReferenceRect.UpperLeftCorner.Y + y);
\r
235 XWarpPointer(Device->XDisplay,
\r
237 Device->XWindow, 0, 0,
\r
240 ReferenceRect.UpperLeftCorner.X + x,
\r
241 ReferenceRect.UpperLeftCorner.Y + y);
\r
246 #ifdef _IRR_LINUX_X11_XINPUT2_
\r
247 if ( DeviceId != 0)
\r
249 XIWarpPointer(Device->XDisplay,
\r
252 Device->XWindow, 0, 0,
\r
254 Device->Height, x, y);
\r
259 XWarpPointer(Device->XDisplay,
\r
261 Device->XWindow, 0, 0,
\r
263 Device->Height, x, y);
\r
266 XFlush(Device->XDisplay);
\r
273 //! Returns the current position of the mouse cursor.
\r
274 const core::position2d<s32>& getPosition(bool updateCursor) override
\r
276 if ( updateCursor )
\r
281 //! Returns the current position of the mouse cursor.
\r
282 core::position2d<f32> getRelativePosition(bool updateCursor) override
\r
284 if ( updateCursor )
\r
287 if (!UseReferenceRect)
\r
289 return core::position2d<f32>(CursorPos.X / (f32)Device->Width,
\r
290 CursorPos.Y / (f32)Device->Height);
\r
293 return core::position2d<f32>(CursorPos.X / (f32)ReferenceRect.getWidth(),
\r
294 CursorPos.Y / (f32)ReferenceRect.getHeight());
\r
297 void setReferenceRect(core::rect<s32>* rect=0) override
\r
301 ReferenceRect = *rect;
\r
302 UseReferenceRect = true;
\r
304 // prevent division through zero and uneven sizes
\r
306 if (!ReferenceRect.getHeight() || ReferenceRect.getHeight()%2)
\r
307 ReferenceRect.LowerRightCorner.Y += 1;
\r
309 if (!ReferenceRect.getWidth() || ReferenceRect.getWidth()%2)
\r
310 ReferenceRect.LowerRightCorner.X += 1;
\r
313 UseReferenceRect = false;
\r
316 //! Sets the active cursor icon
\r
317 void setActiveIcon(gui::ECURSOR_ICON iconId) override;
\r
319 //! Gets the currently active icon
\r
320 gui::ECURSOR_ICON getActiveIcon() const override
\r
325 //! Add a custom sprite as cursor icon.
\r
326 gui::ECURSOR_ICON addIcon(const gui::SCursorSprite& icon) override;
\r
328 //! replace the given cursor icon.
\r
329 void changeIcon(gui::ECURSOR_ICON iconId, const gui::SCursorSprite& icon) override;
\r
331 //! Return a system-specific size which is supported for cursors. Larger icons will fail, smaller icons might work.
\r
332 core::dimension2di getSupportedIconSize() const override;
\r
334 #ifdef _IRR_COMPILE_WITH_X11_
\r
335 //! Set platform specific behavior flags.
\r
336 void setPlatformBehavior(gui::ECURSOR_PLATFORM_BEHAVIOR behavior) override {PlatformBehavior = behavior; }
\r
338 //! Return platform specific behavior.
\r
339 gui::ECURSOR_PLATFORM_BEHAVIOR getPlatformBehavior() const override { return PlatformBehavior; }
\r
342 void clearCursors();
\r
346 void updateCursorPos()
\r
348 #ifdef _IRR_COMPILE_WITH_X11_
\r
352 if ( PlatformBehavior&gui::ECPB_X11_CACHE_UPDATES && !os::Timer::isStopped() )
\r
354 u32 now = os::Timer::getTime();
\r
355 if (now <= LastQuery)
\r
362 unsigned int maskreturn;
\r
363 XQueryPointer(Device->XDisplay, Device->XWindow,
\r
366 &CursorPos.X, &CursorPos.Y, &maskreturn);
\r
370 CIrrDeviceLinux* Device;
\r
371 core::position2d<s32> CursorPos;
\r
372 core::rect<s32> ReferenceRect;
\r
373 #ifdef _IRR_COMPILE_WITH_X11_
\r
374 gui::ECURSOR_PLATFORM_BEHAVIOR PlatformBehavior;
\r
376 Cursor InvisCursor;
\r
378 #ifdef _IRR_LINUX_X11_XINPUT2_
\r
382 struct CursorFrameX11
\r
384 CursorFrameX11() : IconHW(0) {}
\r
385 CursorFrameX11(Cursor icon) : IconHW(icon) {}
\r
387 Cursor IconHW; // hardware cursor
\r
393 explicit CursorX11(Cursor iconHw, u32 frameTime=0) : FrameTime(frameTime)
\r
395 Frames.push_back( CursorFrameX11(iconHw) );
\r
397 core::array<CursorFrameX11> Frames;
\r
401 core::array<CursorX11> Cursors;
\r
403 void initCursors();
\r
407 bool UseReferenceRect;
\r
408 gui::ECURSOR_ICON ActiveIcon;
\r
409 u32 ActiveIconStartTime;
\r
412 friend class CCursorControl;
\r
414 #ifdef _IRR_COMPILE_WITH_X11_
\r
415 friend class COpenGLDriver;
\r
418 XVisualInfo* VisualInfo;
\r
421 XSetWindowAttributes WndAttributes;
\r
422 XSizeHints* StdHints;
\r
427 mutable core::stringc Clipboard;
\r
428 mutable core::stringc PrimarySelection;
\r
430 #if defined(_IRR_LINUX_X11_XINPUT2_)
\r
431 int currentTouchedCount;
\r
434 bool WindowHasFocus;
\r
435 bool WindowMinimized;
\r
436 bool WindowMaximized;
\r
437 bool ExternalWindow;
\r
438 int AutorepeatSupport;
\r
443 SKeyMap(s32 x11, s32 win32)
\r
444 : X11Key(x11), Win32Key(win32)
\r
451 bool operator<(const SKeyMap& o) const
\r
453 return X11Key<o.X11Key;
\r
457 core::array<SKeyMap> KeyMap;
\r
459 #if defined(_IRR_COMPILE_WITH_JOYSTICK_EVENTS_)
\r
460 struct JoystickInfo
\r
466 SEvent persistentData;
\r
468 JoystickInfo() : fd(-1), axes(0), buttons(0) { }
\r
470 core::array<JoystickInfo> ActiveJoysticks;
\r
475 } // end namespace irr
\r
477 #endif // _IRR_COMPILE_WITH_X11_DEVICE_
\r
478 #endif // __C_IRR_DEVICE_LINUX_H_INCLUDED__
\r