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