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 "IImagePresenter.h"
\r
15 #include "ICursorControl.h"
\r
18 #ifdef _IRR_COMPILE_WITH_X11_
\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
26 #ifdef _IRR_LINUX_X11_RANDR_
\r
27 #include <X11/extensions/Xrandr.h>
\r
29 #include <X11/keysym.h>
\r
31 #ifdef _IRR_LINUX_X11_XINPUT2_
\r
32 #include <X11/extensions/XInput2.h>
\r
42 class CIrrDeviceLinux : public CIrrDeviceStub, public video::IImagePresenter
\r
47 CIrrDeviceLinux(const SIrrlichtCreationParameters& param);
\r
50 virtual ~CIrrDeviceLinux();
\r
52 //! runs the device. Returns false if device wants to be deleted
\r
53 virtual bool run() _IRR_OVERRIDE_;
\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
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
62 //! sets the caption of the window
\r
63 virtual void setWindowCaption(const wchar_t* text) _IRR_OVERRIDE_;
\r
65 //! returns if window is active. if not, nothing need to be drawn
\r
66 virtual bool isWindowActive() const _IRR_OVERRIDE_;
\r
68 //! returns if window has focus.
\r
69 virtual bool isWindowFocused() const _IRR_OVERRIDE_;
\r
71 //! returns if window is minimized.
\r
72 virtual bool isWindowMinimized() const _IRR_OVERRIDE_;
\r
74 //! returns color format of the window.
\r
75 virtual video::ECOLOR_FORMAT getColorFormat() const _IRR_OVERRIDE_;
\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
80 //! notifies the device that it should close itself
\r
81 virtual void closeDevice() _IRR_OVERRIDE_;
\r
83 //! Sets if the window should be resizable in windowed mode.
\r
84 virtual void setResizable(bool resize=false) _IRR_OVERRIDE_;
\r
86 //! Resize the render window.
\r
87 virtual void setWindowSize(const irr::core::dimension2d<u32>& size) _IRR_OVERRIDE_;
\r
89 //! Minimizes the window.
\r
90 virtual void minimizeWindow() _IRR_OVERRIDE_;
\r
92 //! Maximizes the window.
\r
93 virtual void maximizeWindow() _IRR_OVERRIDE_;
\r
95 //! Restores the window size.
\r
96 virtual void restoreWindow() _IRR_OVERRIDE_;
\r
98 //! Get the position of this window on screen
\r
99 virtual core::position2di getWindowPosition() _IRR_OVERRIDE_;
\r
101 //! Activate any joysticks, and generate events for them.
\r
102 virtual bool activateJoysticks(core::array<SJoystickInfo> & joystickInfo) _IRR_OVERRIDE_;
\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
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
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
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
118 //! Remove all messages pending in the system message loop
\r
119 virtual void clearSystemMessages() _IRR_OVERRIDE_;
\r
121 //! Get the device type
\r
122 virtual E_DEVICE_TYPE getType() const _IRR_OVERRIDE_
\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
138 //! create the driver
\r
139 void createDriver();
\r
141 bool createWindow();
\r
143 void createKeyMap();
\r
145 void pollJoysticks();
\r
149 void initXInput2();
\r
151 bool switchToFullscreen();
\r
153 #ifdef _IRR_COMPILE_WITH_X11_
\r
154 bool createInputContext();
\r
155 void destroyInputContext();
\r
156 EKEY_CODE getKeyCode(XEvent &event);
\r
159 //! Implementation of the linux cursor control
\r
160 class CCursorControl : public gui::ICursorControl
\r
164 CCursorControl(CIrrDeviceLinux* dev, bool null);
\r
168 //! Changes the visible state of the mouse cursor.
\r
169 virtual void setVisible(bool visible) _IRR_OVERRIDE_
\r
171 if (visible==IsVisible)
\r
173 IsVisible = visible;
\r
174 #ifdef _IRR_COMPILE_WITH_X11_
\r
178 XDefineCursor( Device->XDisplay, Device->XWindow, InvisCursor );
\r
180 XUndefineCursor( Device->XDisplay, Device->XWindow );
\r
185 //! Returns if the cursor is currently visible.
\r
186 virtual bool isVisible() const _IRR_OVERRIDE_
\r
191 //! Sets the new position of the cursor.
\r
192 virtual void setPosition(const core::position2d<f32> &pos) _IRR_OVERRIDE_
\r
194 setPosition(pos.X, pos.Y);
\r
197 //! Sets the new position of the cursor.
\r
198 virtual void setPosition(f32 x, f32 y) _IRR_OVERRIDE_
\r
200 setPosition((s32)(x*Device->Width), (s32)(y*Device->Height));
\r
203 //! Sets the new position of the cursor.
\r
204 virtual void setPosition(const core::position2d<s32> &pos) _IRR_OVERRIDE_
\r
206 setPosition(pos.X, pos.Y);
\r
209 //! Sets the new position of the cursor.
\r
210 virtual void setPosition(s32 x, s32 y) _IRR_OVERRIDE_
\r
212 #ifdef _IRR_COMPILE_WITH_X11_
\r
216 if (UseReferenceRect)
\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
224 XIWarpPointer(Device->XDisplay,
\r
227 Device->XWindow, 0, 0,
\r
230 ReferenceRect.UpperLeftCorner.X + x,
\r
231 ReferenceRect.UpperLeftCorner.Y + y);
\r
236 XWarpPointer(Device->XDisplay,
\r
238 Device->XWindow, 0, 0,
\r
241 ReferenceRect.UpperLeftCorner.X + x,
\r
242 ReferenceRect.UpperLeftCorner.Y + y);
\r
247 #ifdef _IRR_LINUX_X11_XINPUT2_
\r
248 if ( DeviceId != 0)
\r
250 XIWarpPointer(Device->XDisplay,
\r
253 Device->XWindow, 0, 0,
\r
255 Device->Height, x, y);
\r
260 XWarpPointer(Device->XDisplay,
\r
262 Device->XWindow, 0, 0,
\r
264 Device->Height, x, y);
\r
267 XFlush(Device->XDisplay);
\r
274 //! Returns the current position of the mouse cursor.
\r
275 virtual const core::position2d<s32>& getPosition(bool updateCursor) _IRR_OVERRIDE_
\r
277 if ( updateCursor )
\r
282 //! Returns the current position of the mouse cursor.
\r
283 virtual core::position2d<f32> getRelativePosition(bool updateCursor) _IRR_OVERRIDE_
\r
285 if ( updateCursor )
\r
288 if (!UseReferenceRect)
\r
290 return core::position2d<f32>(CursorPos.X / (f32)Device->Width,
\r
291 CursorPos.Y / (f32)Device->Height);
\r
294 return core::position2d<f32>(CursorPos.X / (f32)ReferenceRect.getWidth(),
\r
295 CursorPos.Y / (f32)ReferenceRect.getHeight());
\r
298 virtual void setReferenceRect(core::rect<s32>* rect=0) _IRR_OVERRIDE_
\r
302 ReferenceRect = *rect;
\r
303 UseReferenceRect = true;
\r
305 // prevent division through zero and uneven sizes
\r
307 if (!ReferenceRect.getHeight() || ReferenceRect.getHeight()%2)
\r
308 ReferenceRect.LowerRightCorner.Y += 1;
\r
310 if (!ReferenceRect.getWidth() || ReferenceRect.getWidth()%2)
\r
311 ReferenceRect.LowerRightCorner.X += 1;
\r
314 UseReferenceRect = false;
\r
317 //! Sets the active cursor icon
\r
318 virtual void setActiveIcon(gui::ECURSOR_ICON iconId) _IRR_OVERRIDE_;
\r
320 //! Gets the currently active icon
\r
321 virtual gui::ECURSOR_ICON getActiveIcon() const _IRR_OVERRIDE_
\r
326 //! Add a custom sprite as cursor icon.
\r
327 virtual gui::ECURSOR_ICON addIcon(const gui::SCursorSprite& icon) _IRR_OVERRIDE_;
\r
329 //! replace the given cursor icon.
\r
330 virtual void changeIcon(gui::ECURSOR_ICON iconId, const gui::SCursorSprite& icon) _IRR_OVERRIDE_;
\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
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
339 //! Return platform specific behavior.
\r
340 virtual gui::ECURSOR_PLATFORM_BEHAVIOR getPlatformBehavior() const _IRR_OVERRIDE_ { return PlatformBehavior; }
\r
343 void clearCursors();
\r
347 void updateCursorPos()
\r
349 #ifdef _IRR_COMPILE_WITH_X11_
\r
353 if ( PlatformBehavior&gui::ECPB_X11_CACHE_UPDATES && !os::Timer::isStopped() )
\r
355 u32 now = os::Timer::getTime();
\r
356 if (now <= LastQuery)
\r
363 unsigned int maskreturn;
\r
364 XQueryPointer(Device->XDisplay, Device->XWindow,
\r
367 &CursorPos.X, &CursorPos.Y, &maskreturn);
\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
377 Cursor InvisCursor;
\r
379 #ifdef _IRR_LINUX_X11_XINPUT2_
\r
383 struct CursorFrameX11
\r
385 CursorFrameX11() : IconHW(0) {}
\r
386 CursorFrameX11(Cursor icon) : IconHW(icon) {}
\r
388 Cursor IconHW; // hardware cursor
\r
394 explicit CursorX11(Cursor iconHw, u32 frameTime=0) : FrameTime(frameTime)
\r
396 Frames.push_back( CursorFrameX11(iconHw) );
\r
398 core::array<CursorFrameX11> Frames;
\r
402 core::array<CursorX11> Cursors;
\r
404 void initCursors();
\r
408 bool UseReferenceRect;
\r
409 gui::ECURSOR_ICON ActiveIcon;
\r
410 u32 ActiveIconStartTime;
\r
413 friend class CCursorControl;
\r
415 #ifdef _IRR_COMPILE_WITH_X11_
\r
416 friend class COpenGLDriver;
\r
419 XVisualInfo* VisualInfo;
\r
422 XSetWindowAttributes WndAttributes;
\r
423 XSizeHints* StdHints;
\r
424 XImage* SoftwareImage;
\r
428 mutable core::stringc Clipboard;
\r
431 bool WindowHasFocus;
\r
432 bool WindowMinimized;
\r
433 bool ExternalWindow;
\r
434 int AutorepeatSupport;
\r
439 SKeyMap(s32 x11, s32 win32)
\r
440 : X11Key(x11), Win32Key(win32)
\r
447 bool operator<(const SKeyMap& o) const
\r
449 return X11Key<o.X11Key;
\r
453 core::array<SKeyMap> KeyMap;
\r
455 #if defined(_IRR_COMPILE_WITH_JOYSTICK_EVENTS_)
\r
456 struct JoystickInfo
\r
462 SEvent persistentData;
\r
464 JoystickInfo() : fd(-1), axes(0), buttons(0) { }
\r
466 core::array<JoystickInfo> ActiveJoysticks;
\r
469 #if defined(_IRR_LINUX_X11_XINPUT2_)
\r
470 int currentTouchedCount;
\r
475 } // end namespace irr
\r
477 #endif // _IRR_COMPILE_WITH_X11_DEVICE_
\r
478 #endif // __C_IRR_DEVICE_LINUX_H_INCLUDED__
\r