The exact commands to make this commit were: git reset --hard origin/master find -type f | # list all regular files grep -E '\.(h|cpp|fsh|vsh|mm)|LICENSE$' | # filter for text files xargs -n 1 -P $(nproc) sed -i 's:\s*$::' # for each file, trim trailing whitespace including the CR git commit -a
		
			
				
	
	
		
			484 lines
		
	
	
		
			12 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
			
		
		
	
	
			484 lines
		
	
	
		
			12 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
| // Copyright (C) 2002-2012 Nikolaus Gebhardt
 | |
| // This file is part of the "Irrlicht Engine".
 | |
| // For conditions of distribution and use, see copyright notice in irrlicht.h
 | |
| 
 | |
| #pragma once
 | |
| 
 | |
| #ifdef _IRR_COMPILE_WITH_X11_DEVICE_
 | |
| 
 | |
| #include "CIrrDeviceStub.h"
 | |
| #include "IrrlichtDevice.h"
 | |
| #include "ICursorControl.h"
 | |
| #include "os.h"
 | |
| 
 | |
| #ifdef _IRR_COMPILE_WITH_X11_
 | |
| 
 | |
| #include <X11/Xlib.h>
 | |
| #include <X11/Xutil.h>
 | |
| #include <X11/cursorfont.h>
 | |
| #include <X11/keysym.h>
 | |
| 
 | |
| #ifdef _IRR_LINUX_X11_XINPUT2_
 | |
| #include <X11/extensions/XInput2.h>
 | |
| #endif
 | |
| 
 | |
| #else
 | |
| #define KeySym s32
 | |
| #endif
 | |
| 
 | |
| namespace irr
 | |
| {
 | |
| 
 | |
| 	class CIrrDeviceLinux : public CIrrDeviceStub
 | |
| 	{
 | |
| 	public:
 | |
| 
 | |
| 		//! constructor
 | |
| 		CIrrDeviceLinux(const SIrrlichtCreationParameters& param);
 | |
| 
 | |
| 		//! destructor
 | |
| 		virtual ~CIrrDeviceLinux();
 | |
| 
 | |
| 		//! runs the device. Returns false if device wants to be deleted
 | |
| 		bool run() override;
 | |
| 
 | |
| 		//! Cause the device to temporarily pause execution and let other processes to run
 | |
| 		// This should bring down processor usage without major performance loss for Irrlicht
 | |
| 		void yield() override;
 | |
| 
 | |
| 		//! Pause execution and let other processes to run for a specified amount of time.
 | |
| 		void sleep(u32 timeMs, bool pauseTimer) override;
 | |
| 
 | |
| 		//! sets the caption of the window
 | |
| 		void setWindowCaption(const wchar_t* text) override;
 | |
| 
 | |
| 		//! Sets the window icon.
 | |
| 		bool setWindowIcon(const video::IImage *img) override;
 | |
| 
 | |
| 		//! returns if window is active. if not, nothing need to be drawn
 | |
| 		bool isWindowActive() const override;
 | |
| 
 | |
| 		//! returns if window has focus.
 | |
| 		bool isWindowFocused() const override;
 | |
| 
 | |
| 		//! returns if window is minimized.
 | |
| 		bool isWindowMinimized() const override;
 | |
| 
 | |
| 		//! returns last state from maximizeWindow() and restoreWindow()
 | |
| 		bool isWindowMaximized() const override;
 | |
| 
 | |
| 		//! returns color format of the window.
 | |
| 		video::ECOLOR_FORMAT getColorFormat() const override;
 | |
| 
 | |
| 		//! notifies the device that it should close itself
 | |
| 		void closeDevice() override;
 | |
| 
 | |
| 		//! Sets if the window should be resizable in windowed mode.
 | |
| 		void setResizable(bool resize=false) override;
 | |
| 
 | |
| 		//! Resize the render window.
 | |
| 		void setWindowSize(const irr::core::dimension2d<u32>& size) override;
 | |
| 
 | |
| 		//! Minimizes the window.
 | |
| 		void minimizeWindow() override;
 | |
| 
 | |
| 		//! Maximizes the window.
 | |
| 		void maximizeWindow() override;
 | |
| 
 | |
| 		//! Restores the window size.
 | |
| 		void restoreWindow() override;
 | |
| 
 | |
| 		//! Get the position of this window on screen
 | |
| 		core::position2di getWindowPosition() override;
 | |
| 
 | |
| 		//! Activate any joysticks, and generate events for them.
 | |
| 		bool activateJoysticks(core::array<SJoystickInfo> & joystickInfo) override;
 | |
| 
 | |
| 		//! gets text from the clipboard
 | |
| 		//! \return Returns 0 if no string is in there, otherwise utf-8 text.
 | |
| 		virtual const c8 *getTextFromClipboard() const;
 | |
| 
 | |
| 		//! gets text from the primary selection
 | |
| 		//! \return Returns 0 if no string is in there, otherwise utf-8 text.
 | |
| 		virtual const c8 *getTextFromPrimarySelection() const;
 | |
| 
 | |
| 		//! copies text to the clipboard
 | |
| 		//! This sets the clipboard selection and _not_ the primary selection.
 | |
| 		//! @param text The text in utf-8
 | |
| 		virtual void copyToClipboard(const c8 *text) const;
 | |
| 
 | |
| 		//! copies text to the primary selection
 | |
| 		//! This sets the primary selection which you have on X on the middle mouse button.
 | |
| 		//! @param text The text in utf-8
 | |
| 		virtual void copyToPrimarySelection(const c8 *text) const;
 | |
| 
 | |
| 		//! Remove all messages pending in the system message loop
 | |
| 		void clearSystemMessages() override;
 | |
| 
 | |
| 		//! Get the device type
 | |
| 		E_DEVICE_TYPE getType() const override
 | |
| 		{
 | |
| 			return EIDT_X11;
 | |
| 		}
 | |
| 
 | |
| 		//! Get the display density in dots per inch.
 | |
| 		float getDisplayDensity() const override;
 | |
| 
 | |
| #ifdef _IRR_COMPILE_WITH_X11_
 | |
| 		// convert an Irrlicht texture to a X11 cursor
 | |
| 		Cursor TextureToCursor(irr::video::ITexture * tex, const core::rect<s32>& sourceRect, const core::position2d<s32> &hotspot);
 | |
| 		Cursor TextureToMonochromeCursor(irr::video::ITexture * tex, const core::rect<s32>& sourceRect, const core::position2d<s32> &hotspot);
 | |
| #ifdef _IRR_LINUX_XCURSOR_
 | |
| 		Cursor TextureToARGBCursor(irr::video::ITexture * tex, const core::rect<s32>& sourceRect, const core::position2d<s32> &hotspot);
 | |
| #endif
 | |
| #endif
 | |
| 
 | |
| 	private:
 | |
| 
 | |
| 		//! create the driver
 | |
| 		void createDriver();
 | |
| 
 | |
| 		bool createWindow();
 | |
| 
 | |
| 		void createKeyMap();
 | |
| 
 | |
| 		void pollJoysticks();
 | |
| 
 | |
| 		void initXAtoms();
 | |
| 
 | |
| 		void initXInput2();
 | |
| 
 | |
| 		bool switchToFullscreen();
 | |
| 
 | |
| 		void setupTopLevelXorgWindow();
 | |
| 
 | |
| #ifdef _IRR_COMPILE_WITH_X11_
 | |
| 		bool createInputContext();
 | |
| 		void destroyInputContext();
 | |
| 		EKEY_CODE getKeyCode(XEvent &event);
 | |
| 
 | |
| 		const c8 *getTextFromSelection(Atom selection, core::stringc &text_buffer) const;
 | |
| 		bool becomeSelectionOwner(Atom selection) const;
 | |
| #endif
 | |
| 
 | |
| 		//! Implementation of the linux cursor control
 | |
| 		class CCursorControl : public gui::ICursorControl
 | |
| 		{
 | |
| 		public:
 | |
| 
 | |
| 			CCursorControl(CIrrDeviceLinux* dev, bool null);
 | |
| 
 | |
| 			~CCursorControl();
 | |
| 
 | |
| 			//! Changes the visible state of the mouse cursor.
 | |
| 			void setVisible(bool visible) override
 | |
| 			{
 | |
| 				if (visible==IsVisible)
 | |
| 					return;
 | |
| 				IsVisible = visible;
 | |
| #ifdef _IRR_COMPILE_WITH_X11_
 | |
| 				if (!Null)
 | |
| 				{
 | |
| 					if ( !IsVisible )
 | |
| 						XDefineCursor( Device->XDisplay, Device->XWindow, InvisCursor );
 | |
| 					else
 | |
| 						XUndefineCursor( Device->XDisplay, Device->XWindow );
 | |
| 				}
 | |
| #endif
 | |
| 			}
 | |
| 
 | |
| 			//! Returns if the cursor is currently visible.
 | |
| 			bool isVisible() const override
 | |
| 			{
 | |
| 				return IsVisible;
 | |
| 			}
 | |
| 
 | |
| 			//! Sets the new position of the cursor.
 | |
| 			void setPosition(const core::position2d<f32> &pos) override
 | |
| 			{
 | |
| 				setPosition(pos.X, pos.Y);
 | |
| 			}
 | |
| 
 | |
| 			//! Sets the new position of the cursor.
 | |
| 			void setPosition(f32 x, f32 y) override
 | |
| 			{
 | |
| 				setPosition((s32)(x*Device->Width), (s32)(y*Device->Height));
 | |
| 			}
 | |
| 
 | |
| 			//! Sets the new position of the cursor.
 | |
| 			void setPosition(const core::position2d<s32> &pos) override
 | |
| 			{
 | |
| 				setPosition(pos.X, pos.Y);
 | |
| 			}
 | |
| 
 | |
| 			//! Sets the new position of the cursor.
 | |
| 			void setPosition(s32 x, s32 y) override
 | |
| 			{
 | |
| #ifdef _IRR_COMPILE_WITH_X11_
 | |
| 
 | |
| 				if (!Null)
 | |
| 				{
 | |
| 					if (UseReferenceRect)
 | |
| 					{
 | |
| // NOTE: XIWarpPointer works when X11 has set a coordinate transformation matrix for the mouse unlike XWarpPointer
 | |
| // which runs into a bug mentioned here: https://gitlab.freedesktop.org/xorg/xserver/-/issues/600
 | |
| // So also workaround for Irrlicht bug #450
 | |
| #ifdef _IRR_LINUX_X11_XINPUT2_
 | |
| 						if ( DeviceId != 0)
 | |
| 						{
 | |
| 							XIWarpPointer(Device->XDisplay,
 | |
| 								DeviceId,
 | |
| 								None,
 | |
| 								Device->XWindow, 0, 0,
 | |
| 								Device->Width,
 | |
| 								Device->Height,
 | |
| 								ReferenceRect.UpperLeftCorner.X + x,
 | |
| 								ReferenceRect.UpperLeftCorner.Y + y);
 | |
| 						}
 | |
| 						else
 | |
| #endif
 | |
| 						{
 | |
| 							XWarpPointer(Device->XDisplay,
 | |
| 								None,
 | |
| 								Device->XWindow, 0, 0,
 | |
| 								Device->Width,
 | |
| 								Device->Height,
 | |
| 								ReferenceRect.UpperLeftCorner.X + x,
 | |
| 								ReferenceRect.UpperLeftCorner.Y + y);
 | |
| 						}
 | |
| 					}
 | |
| 					else
 | |
| 					{
 | |
| #ifdef _IRR_LINUX_X11_XINPUT2_
 | |
| 						if ( DeviceId != 0)
 | |
| 						{
 | |
| 							XIWarpPointer(Device->XDisplay,
 | |
| 								DeviceId,
 | |
| 								None,
 | |
| 								Device->XWindow, 0, 0,
 | |
| 								Device->Width,
 | |
| 								Device->Height, x, y);
 | |
| 						}
 | |
| 						else
 | |
| #endif
 | |
| 						{
 | |
| 							XWarpPointer(Device->XDisplay,
 | |
| 								None,
 | |
| 								Device->XWindow, 0, 0,
 | |
| 								Device->Width,
 | |
| 								Device->Height, x, y);
 | |
| 						}
 | |
| 					}
 | |
| 					XFlush(Device->XDisplay);
 | |
| 				}
 | |
| #endif
 | |
| 				CursorPos.X = x;
 | |
| 				CursorPos.Y = y;
 | |
| 			}
 | |
| 
 | |
| 			//! Returns the current position of the mouse cursor.
 | |
| 			const core::position2d<s32>& getPosition(bool updateCursor) override
 | |
| 			{
 | |
| 				if ( updateCursor )
 | |
| 					updateCursorPos();
 | |
| 				return CursorPos;
 | |
| 			}
 | |
| 
 | |
| 			//! Returns the current position of the mouse cursor.
 | |
| 			core::position2d<f32> getRelativePosition(bool updateCursor) override
 | |
| 			{
 | |
| 				if ( updateCursor )
 | |
| 					updateCursorPos();
 | |
| 
 | |
| 				if (!UseReferenceRect)
 | |
| 				{
 | |
| 					return core::position2d<f32>(CursorPos.X / (f32)Device->Width,
 | |
| 						CursorPos.Y / (f32)Device->Height);
 | |
| 				}
 | |
| 
 | |
| 				return core::position2d<f32>(CursorPos.X / (f32)ReferenceRect.getWidth(),
 | |
| 						CursorPos.Y / (f32)ReferenceRect.getHeight());
 | |
| 			}
 | |
| 
 | |
| 			void setReferenceRect(core::rect<s32>* rect=0) override
 | |
| 			{
 | |
| 				if (rect)
 | |
| 				{
 | |
| 					ReferenceRect = *rect;
 | |
| 					UseReferenceRect = true;
 | |
| 
 | |
| 					// prevent division through zero and uneven sizes
 | |
| 
 | |
| 					if (!ReferenceRect.getHeight() || ReferenceRect.getHeight()%2)
 | |
| 						ReferenceRect.LowerRightCorner.Y += 1;
 | |
| 
 | |
| 					if (!ReferenceRect.getWidth() || ReferenceRect.getWidth()%2)
 | |
| 						ReferenceRect.LowerRightCorner.X += 1;
 | |
| 				}
 | |
| 				else
 | |
| 					UseReferenceRect = false;
 | |
| 			}
 | |
| 
 | |
| 			//! Sets the active cursor icon
 | |
| 			void setActiveIcon(gui::ECURSOR_ICON iconId) override;
 | |
| 
 | |
| 			//! Gets the currently active icon
 | |
| 			gui::ECURSOR_ICON getActiveIcon() const override
 | |
| 			{
 | |
| 				return ActiveIcon;
 | |
| 			}
 | |
| 
 | |
| 			//! Add a custom sprite as cursor icon.
 | |
| 			gui::ECURSOR_ICON addIcon(const gui::SCursorSprite& icon) override;
 | |
| 
 | |
| 			//! replace the given cursor icon.
 | |
| 			void changeIcon(gui::ECURSOR_ICON iconId, const gui::SCursorSprite& icon) override;
 | |
| 
 | |
| 			//! Return a system-specific size which is supported for cursors. Larger icons will fail, smaller icons might work.
 | |
| 			core::dimension2di getSupportedIconSize() const override;
 | |
| 
 | |
| #ifdef _IRR_COMPILE_WITH_X11_
 | |
| 			//! Set platform specific behavior flags.
 | |
| 			void setPlatformBehavior(gui::ECURSOR_PLATFORM_BEHAVIOR behavior) override {PlatformBehavior = behavior; }
 | |
| 
 | |
| 			//! Return platform specific behavior.
 | |
| 			gui::ECURSOR_PLATFORM_BEHAVIOR getPlatformBehavior() const override { return PlatformBehavior; }
 | |
| 
 | |
| 			void update();
 | |
| 			void clearCursors();
 | |
| #endif
 | |
| 		private:
 | |
| 
 | |
| 			void updateCursorPos()
 | |
| 			{
 | |
| #ifdef _IRR_COMPILE_WITH_X11_
 | |
| 				if (Null)
 | |
| 					return;
 | |
| 
 | |
| 				if ( PlatformBehavior&gui::ECPB_X11_CACHE_UPDATES && !os::Timer::isStopped() )
 | |
| 				{
 | |
| 					u32 now = os::Timer::getTime();
 | |
| 					if (now <= LastQuery)
 | |
| 						return;
 | |
| 					LastQuery = now;
 | |
| 				}
 | |
| 
 | |
| 				Window tmp;
 | |
| 				int itmp1, itmp2;
 | |
| 				unsigned  int maskreturn;
 | |
| 				XQueryPointer(Device->XDisplay, Device->XWindow,
 | |
| 					&tmp, &tmp,
 | |
| 					&itmp1, &itmp2,
 | |
| 					&CursorPos.X, &CursorPos.Y, &maskreturn);
 | |
| #endif
 | |
| 			}
 | |
| 
 | |
| 			CIrrDeviceLinux* Device;
 | |
| 			core::position2d<s32> CursorPos;
 | |
| 			core::rect<s32> ReferenceRect;
 | |
| #ifdef _IRR_COMPILE_WITH_X11_
 | |
| 			gui::ECURSOR_PLATFORM_BEHAVIOR PlatformBehavior;
 | |
| 			u32 LastQuery;
 | |
| 			Cursor InvisCursor;
 | |
| 
 | |
| #ifdef _IRR_LINUX_X11_XINPUT2_
 | |
| 			int DeviceId;
 | |
| #endif
 | |
| 
 | |
| 			struct CursorFrameX11
 | |
| 			{
 | |
| 				CursorFrameX11() : IconHW(0) {}
 | |
| 				CursorFrameX11(Cursor icon) : IconHW(icon) {}
 | |
| 
 | |
| 				Cursor IconHW;	// hardware cursor
 | |
| 			};
 | |
| 
 | |
| 			struct CursorX11
 | |
| 			{
 | |
| 				CursorX11() {}
 | |
| 				explicit CursorX11(Cursor iconHw, u32 frameTime=0) : FrameTime(frameTime)
 | |
| 				{
 | |
| 					Frames.push_back( CursorFrameX11(iconHw) );
 | |
| 				}
 | |
| 				core::array<CursorFrameX11> Frames;
 | |
| 				u32 FrameTime;
 | |
| 			};
 | |
| 
 | |
| 			core::array<CursorX11> Cursors;
 | |
| 
 | |
| 			void initCursors();
 | |
| #endif
 | |
| 			bool IsVisible;
 | |
| 			bool Null;
 | |
| 			bool UseReferenceRect;
 | |
| 			gui::ECURSOR_ICON ActiveIcon;
 | |
| 			u32 ActiveIconStartTime;
 | |
| 		};
 | |
| 
 | |
| 		friend class CCursorControl;
 | |
| 
 | |
| #ifdef _IRR_COMPILE_WITH_X11_
 | |
| 		friend class COpenGLDriver;
 | |
| 
 | |
| 		Display *XDisplay;
 | |
| 		XVisualInfo* VisualInfo;
 | |
| 		int Screennr;
 | |
| 		Window XWindow;
 | |
| 		XSetWindowAttributes WndAttributes;
 | |
| 		XSizeHints* StdHints;
 | |
| 		XIM XInputMethod;
 | |
| 		XIC XInputContext;
 | |
| 		bool HasNetWM;
 | |
| 		// text is utf-8
 | |
| 		mutable core::stringc Clipboard;
 | |
| 		mutable core::stringc PrimarySelection;
 | |
| #endif
 | |
| #if defined(_IRR_LINUX_X11_XINPUT2_)
 | |
| 		int currentTouchedCount;
 | |
| #endif
 | |
| 		u32 Width, Height;
 | |
| 		bool WindowHasFocus;
 | |
| 		bool WindowMinimized;
 | |
| 		bool WindowMaximized;
 | |
| 		bool ExternalWindow;
 | |
| 		int AutorepeatSupport;
 | |
| 
 | |
| 		struct SKeyMap
 | |
| 		{
 | |
| 			SKeyMap() {}
 | |
| 			SKeyMap(s32 x11, s32 win32)
 | |
| 				: X11Key(x11), Win32Key(win32)
 | |
| 			{
 | |
| 			}
 | |
| 
 | |
| 			KeySym X11Key;
 | |
| 			s32 Win32Key;
 | |
| 
 | |
| 			bool operator<(const SKeyMap& o) const
 | |
| 			{
 | |
| 				return X11Key<o.X11Key;
 | |
| 			}
 | |
| 		};
 | |
| 
 | |
| 		core::array<SKeyMap> KeyMap;
 | |
| 
 | |
| #if defined(_IRR_COMPILE_WITH_JOYSTICK_EVENTS_)
 | |
| 		struct JoystickInfo
 | |
| 		{
 | |
| 			int	fd;
 | |
| 			int	axes;
 | |
| 			int	buttons;
 | |
| 
 | |
| 			SEvent persistentData;
 | |
| 
 | |
| 			JoystickInfo() : fd(-1), axes(0), buttons(0) { }
 | |
| 		};
 | |
| 		core::array<JoystickInfo> ActiveJoysticks;
 | |
| #endif
 | |
| 	};
 | |
| 
 | |
| 
 | |
| } // end namespace irr
 | |
| 
 | |
| #endif // _IRR_COMPILE_WITH_X11_DEVICE_
 |