]> git.lizzy.rs Git - irrlicht.git/blobdiff - source/Irrlicht/CIrrDeviceLinux.cpp
Avoid undefined arithmetic on nullptr in buffer_offset function
[irrlicht.git] / source / Irrlicht / CIrrDeviceLinux.cpp
index c4f8d4e70259ceb9d45fed4df4c0083f4362dbaa..3c1909917f4b5a25b53340b6ef1b516dde0ee738 100644 (file)
@@ -110,7 +110,7 @@ namespace irr
 CIrrDeviceLinux::CIrrDeviceLinux(const SIrrlichtCreationParameters& param)\r
        : CIrrDeviceStub(param),\r
 #ifdef _IRR_COMPILE_WITH_X11_\r
-       XDisplay(0), VisualInfo(0), Screennr(0), XWindow(0), StdHints(0), SoftwareImage(0),\r
+       XDisplay(0), VisualInfo(0), Screennr(0), XWindow(0), StdHints(0),\r
        XInputMethod(0), XInputContext(0),\r
        HasNetWM(false),\r
 #endif\r
@@ -118,7 +118,7 @@ CIrrDeviceLinux::CIrrDeviceLinux(const SIrrlichtCreationParameters& param)
        currentTouchedCount(0),\r
 #endif\r
        Width(param.WindowSize.Width), Height(param.WindowSize.Height),\r
-       WindowHasFocus(false), WindowMinimized(false),\r
+       WindowHasFocus(false), WindowMinimized(false), WindowMaximized(param.WindowMaximized),\r
        ExternalWindow(false), AutorepeatSupport(0)\r
 {\r
        #ifdef _DEBUG\r
@@ -168,6 +168,9 @@ CIrrDeviceLinux::CIrrDeviceLinux(const SIrrlichtCreationParameters& param)
                return;\r
 \r
        createGUIAndScene();\r
+\r
+       if (param.WindowMaximized)\r
+               maximizeWindow();\r
 }\r
 \r
 \r
@@ -211,9 +214,6 @@ CIrrDeviceLinux::~CIrrDeviceLinux()
                        ContextManager->destroySurface();\r
                }\r
 \r
-               if (SoftwareImage)\r
-                       XDestroyImage(SoftwareImage);\r
-\r
                if (!ExternalWindow)\r
                {\r
                        XDestroyWindow(XDisplay,XWindow);\r
@@ -287,26 +287,26 @@ void IrrPrintXGrabError(int grabResult, const c8 * grabCommand )
 {\r
        if ( grabResult == GrabSuccess )\r
        {\r
-//             os::Printer::log(grabCommand, "GrabSuccess", ELL_INFORMATION);\r
+//             os::Printer::log(grabCommand, "GrabSuccess", ELL_INFORMATION);\r
                return;\r
        }\r
 \r
        switch ( grabResult )\r
        {\r
                case AlreadyGrabbed:\r
-                       os::Printer::log(grabCommand, "AlreadyGrabbed", ELL_WARNING);\r
+                       os::Printer::log(grabCommand, "AlreadyGrabbed", ELL_WARNING);\r
                        break;\r
                case GrabNotViewable:\r
-                       os::Printer::log(grabCommand, "GrabNotViewable", ELL_WARNING);\r
+                       os::Printer::log(grabCommand, "GrabNotViewable", ELL_WARNING);\r
                        break;\r
                case GrabFrozen:\r
-                       os::Printer::log(grabCommand, "GrabFrozen", ELL_WARNING);\r
+                       os::Printer::log(grabCommand, "GrabFrozen", ELL_WARNING);\r
                        break;\r
                case GrabInvalidTime:\r
-                       os::Printer::log(grabCommand, "GrabInvalidTime", ELL_WARNING);\r
+                       os::Printer::log(grabCommand, "GrabInvalidTime", ELL_WARNING);\r
                        break;\r
                default:\r
-                       os::Printer::log(grabCommand, "grab failed with unknown problem", ELL_WARNING);\r
+                       os::Printer::log(grabCommand, "grab failed with unknown problem", ELL_WARNING);\r
                        break;\r
        }\r
 }\r
@@ -380,7 +380,7 @@ bool CIrrDeviceLinux::createWindow()
        }\r
 #ifdef _DEBUG\r
        else\r
-               os::Printer::log("Visual chosen", core::stringc(static_cast<u32>(VisualInfo->visualid)).c_str(), ELL_DEBUG);\r
+               os::Printer::log("Visual chosen", core::stringc(static_cast<u32>(VisualInfo->visualid)).c_str(), ELL_DEBUG);\r
 #endif\r
 \r
        // create color map\r
@@ -487,21 +487,6 @@ bool CIrrDeviceLinux::createWindow()
        long num;\r
        XGetWMNormalHints(XDisplay, XWindow, StdHints, &num);\r
 \r
-       // create an XImage for the software renderer\r
-       //(thx to Nadav for some clues on how to do that!)\r
-\r
-       if (CreationParams.DriverType == video::EDT_SOFTWARE || CreationParams.DriverType == video::EDT_BURNINGSVIDEO)\r
-       {\r
-               SoftwareImage = XCreateImage(XDisplay,\r
-                       VisualInfo->visual, VisualInfo->depth,\r
-                       ZPixmap, 0, 0, Width, Height,\r
-                       BitmapPad(XDisplay), 0);\r
-\r
-               // use malloc because X will free it later on\r
-               if (SoftwareImage)\r
-                       SoftwareImage->data = (char*) malloc(SoftwareImage->bytes_per_line * SoftwareImage->height * sizeof(char));\r
-       }\r
-\r
        initXInput2();\r
 \r
 #endif // #ifdef _IRR_COMPILE_WITH_X11_\r
@@ -515,20 +500,6 @@ void CIrrDeviceLinux::createDriver()
        switch(CreationParams.DriverType)\r
        {\r
 #ifdef _IRR_COMPILE_WITH_X11_\r
-       case video::EDT_SOFTWARE:\r
-#ifdef _IRR_COMPILE_WITH_SOFTWARE_\r
-               VideoDriver = video::createSoftwareDriver(CreationParams.WindowSize, CreationParams.Fullscreen, FileSystem, this);\r
-#else\r
-               os::Printer::log("No Software driver support compiled in.", ELL_ERROR);\r
-#endif\r
-               break;\r
-       case video::EDT_BURNINGSVIDEO:\r
-#ifdef _IRR_COMPILE_WITH_BURNINGSVIDEO_\r
-               VideoDriver = video::createBurningVideoDriver(CreationParams, FileSystem, this);\r
-#else\r
-               os::Printer::log("Burning's video driver was not compiled in.", ELL_ERROR);\r
-#endif\r
-               break;\r
        case video::EDT_OPENGL:\r
 #ifdef _IRR_COMPILE_WITH_OPENGL_\r
                {\r
@@ -765,21 +736,6 @@ bool CIrrDeviceLinux::run()
                                        Width = event.xconfigure.width;\r
                                        Height = event.xconfigure.height;\r
 \r
-                                       // resize image data\r
-                                       if (SoftwareImage)\r
-                                       {\r
-                                               XDestroyImage(SoftwareImage);\r
-\r
-                                               SoftwareImage = XCreateImage(XDisplay,\r
-                                                       VisualInfo->visual, VisualInfo->depth,\r
-                                                       ZPixmap, 0, 0, Width, Height,\r
-                                                       BitmapPad(XDisplay), 0);\r
-\r
-                                               // use malloc because X will free it later on\r
-                                               if (SoftwareImage)\r
-                                                       SoftwareImage->data = (char*) malloc(SoftwareImage->bytes_per_line * SoftwareImage->height * sizeof(char));\r
-                                       }\r
-\r
                                        if (VideoDriver)\r
                                                VideoDriver->OnResize(core::dimension2d<u32>(Width, Height));\r
                                }\r
@@ -1219,60 +1175,6 @@ void CIrrDeviceLinux::setWindowCaption(const wchar_t* text)
 }\r
 \r
 \r
-//! presents a surface in the client area\r
-bool CIrrDeviceLinux::present(video::IImage* image, void* windowId, core::rect<s32>* srcRect)\r
-{\r
-#ifdef _IRR_COMPILE_WITH_X11_\r
-       // this is only necessary for software drivers.\r
-       if (!SoftwareImage)\r
-               return true;\r
-\r
-       // thx to Nadav, who send me some clues of how to display the image\r
-       // to the X Server.\r
-\r
-       const u32 destwidth = SoftwareImage->width;\r
-       const u32 minWidth = core::min_(image->getDimension().Width, destwidth);\r
-       const u32 destPitch = SoftwareImage->bytes_per_line;\r
-\r
-       video::ECOLOR_FORMAT destColor;\r
-       switch (SoftwareImage->bits_per_pixel)\r
-       {\r
-               case 16:\r
-                       if (SoftwareImage->depth==16)\r
-                               destColor = video::ECF_R5G6B5;\r
-                       else\r
-                               destColor = video::ECF_A1R5G5B5;\r
-               break;\r
-               case 24: destColor = video::ECF_R8G8B8; break;\r
-               case 32: destColor = video::ECF_A8R8G8B8; break;\r
-               default:\r
-                       os::Printer::log("Unsupported screen depth.");\r
-                       return false;\r
-       }\r
-\r
-       u8* srcdata = reinterpret_cast<u8*>(image->getData());\r
-       u8* destData = reinterpret_cast<u8*>(SoftwareImage->data);\r
-\r
-       const u32 destheight = SoftwareImage->height;\r
-       const u32 srcheight = core::min_(image->getDimension().Height, destheight);\r
-       const u32 srcPitch = image->getPitch();\r
-       for (u32 y=0; y!=srcheight; ++y)\r
-       {\r
-               video::CColorConverter::convert_viaFormat(srcdata,image->getColorFormat(), minWidth, destData, destColor);\r
-               srcdata+=srcPitch;\r
-               destData+=destPitch;\r
-       }\r
-\r
-       GC gc = DefaultGC(XDisplay, DefaultScreen(XDisplay));\r
-       Window myWindow=XWindow;\r
-       if (windowId)\r
-               myWindow = reinterpret_cast<Window>(windowId);\r
-       XPutImage(XDisplay, myWindow, gc, SoftwareImage, 0, 0, 0, 0, destwidth, destheight);\r
-#endif\r
-       return true;\r
-}\r
-\r
-\r
 //! notifies the device that it should close itself\r
 void CIrrDeviceLinux::closeDevice()\r
 {\r
@@ -1301,6 +1203,13 @@ bool CIrrDeviceLinux::isWindowMinimized() const
 }\r
 \r
 \r
+//! returns last state from maximizeWindow() and restoreWindow()\r
+bool CIrrDeviceLinux::isWindowMaximized() const\r
+{\r
+       return WindowMaximized;\r
+}\r
+\r
+\r
 //! returns color format of the window.\r
 video::ECOLOR_FORMAT CIrrDeviceLinux::getColorFormat() const\r
 {\r
@@ -1385,6 +1294,8 @@ void CIrrDeviceLinux::maximizeWindow()
        }\r
 \r
        XMapWindow(XDisplay, XWindow);\r
+\r
+       WindowMaximized = true;\r
 #endif\r
 }\r
 \r
@@ -1411,6 +1322,8 @@ void CIrrDeviceLinux::restoreWindow()
        }\r
 \r
        XMapWindow(XDisplay, XWindow);\r
+\r
+       WindowMaximized = false;\r
 #endif\r
 }\r
 \r
@@ -1701,7 +1614,7 @@ bool CIrrDeviceLinux::activateJoysticks(core::array<SJoystickInfo> & joystickInf
        for (joystick = 0; joystick < joystickInfo.size(); ++joystick)\r
        {\r
                char logString[256];\r
-               (void)sprintf(logString, "Found joystick %u, %u axes, %u buttons '%s'",\r
+               snprintf_irr(logString, sizeof(logString), "Found joystick %d, %d axes, %d buttons '%s'",\r
                        joystick, joystickInfo[joystick].Axes,\r
                        joystickInfo[joystick].Buttons, joystickInfo[joystick].Name.c_str());\r
                os::Printer::log(logString, ELL_INFORMATION);\r
@@ -1763,97 +1676,6 @@ void CIrrDeviceLinux::pollJoysticks()
 }\r
 \r
 \r
-//! Set the current Gamma Value for the Display\r
-bool CIrrDeviceLinux::setGammaRamp( f32 red, f32 green, f32 blue, f32 brightness, f32 contrast )\r
-{\r
-       #if defined(_IRR_LINUX_X11_VIDMODE_) || defined(_IRR_LINUX_X11_RANDR_)\r
-       s32 eventbase, errorbase;\r
-       #ifdef _IRR_LINUX_X11_VIDMODE_\r
-       if (XF86VidModeQueryExtension(XDisplay, &eventbase, &errorbase))\r
-       {\r
-               XF86VidModeGamma gamma;\r
-               gamma.red=red;\r
-               gamma.green=green;\r
-               gamma.blue=blue;\r
-               XF86VidModeSetGamma(XDisplay, Screennr, &gamma);\r
-               return true;\r
-       }\r
-       #endif\r
-       #if defined(_IRR_LINUX_X11_VIDMODE_) && defined(_IRR_LINUX_X11_RANDR_)\r
-       else\r
-       #endif\r
-       #ifdef _IRR_LINUX_X11_RANDR_\r
-       if (XRRQueryExtension(XDisplay, &eventbase, &errorbase))\r
-       {\r
-               XRRQueryVersion(XDisplay, &eventbase, &errorbase); // major, minor\r
-               if (eventbase>=1 && errorbase>1)\r
-               {\r
-               #if (RANDR_MAJOR>1 || RANDR_MINOR>1)\r
-                       XRRCrtcGamma *gamma = XRRGetCrtcGamma(XDisplay, Screennr);\r
-                       if (gamma)\r
-                       {\r
-                               *gamma->red=(u16)red;\r
-                               *gamma->green=(u16)green;\r
-                               *gamma->blue=(u16)blue;\r
-                               XRRSetCrtcGamma(XDisplay, Screennr, gamma);\r
-                               XRRFreeGamma(gamma);\r
-                               return true;\r
-                       }\r
-               #endif\r
-               }\r
-       }\r
-       #endif\r
-       #endif\r
-       return false;\r
-}\r
-\r
-\r
-//! Get the current Gamma Value for the Display\r
-bool CIrrDeviceLinux::getGammaRamp( f32 &red, f32 &green, f32 &blue, f32 &brightness, f32 &contrast )\r
-{\r
-       brightness = 0.f;\r
-       contrast = 0.f;\r
-       #if defined(_IRR_LINUX_X11_VIDMODE_) || defined(_IRR_LINUX_X11_RANDR_)\r
-       s32 eventbase, errorbase;\r
-       #ifdef _IRR_LINUX_X11_VIDMODE_\r
-       if (XF86VidModeQueryExtension(XDisplay, &eventbase, &errorbase))\r
-       {\r
-               XF86VidModeGamma gamma;\r
-               XF86VidModeGetGamma(XDisplay, Screennr, &gamma);\r
-               red = gamma.red;\r
-               green = gamma.green;\r
-               blue = gamma.blue;\r
-               return true;\r
-       }\r
-       #endif\r
-       #if defined(_IRR_LINUX_X11_VIDMODE_) && defined(_IRR_LINUX_X11_RANDR_)\r
-       else\r
-       #endif\r
-       #ifdef _IRR_LINUX_X11_RANDR_\r
-       if (XRRQueryExtension(XDisplay, &eventbase, &errorbase))\r
-       {\r
-               XRRQueryVersion(XDisplay, &eventbase, &errorbase); // major, minor\r
-               if (eventbase>=1 && errorbase>1)\r
-               {\r
-               #if (RANDR_MAJOR>1 || RANDR_MINOR>1)\r
-                       XRRCrtcGamma *gamma = XRRGetCrtcGamma(XDisplay, Screennr);\r
-                       if (gamma)\r
-                       {\r
-                               red = *gamma->red;\r
-                               green = *gamma->green;\r
-                               blue= *gamma->blue;\r
-                               XRRFreeGamma(gamma);\r
-                               return true;\r
-                       }\r
-               #endif\r
-               }\r
-       }\r
-       #endif\r
-       #endif\r
-       return false;\r
-}\r
-\r
-\r
 //! gets text from the clipboard\r
 //! \return Returns 0 if no string is in there, otherwise utf-8 text.\r
 const c8 *CIrrDeviceLinux::getTextFromClipboard() const\r
@@ -1974,7 +1796,7 @@ Bool PredicateIsEventType(Display *display, XEvent *event, XPointer arg)
 {\r
        if ( event && event->type == *(int*)arg )\r
        {\r
-//             os::Printer::log("remove event:", core::stringc((int)arg).c_str(), ELL_INFORMATION);\r
+//             os::Printer::log("remove event", core::stringc((int)arg).c_str(), ELL_INFORMATION);\r
                return True;\r
        }\r
        return False;\r
@@ -2209,7 +2031,17 @@ CIrrDeviceLinux::CCursorControl::CCursorControl(CIrrDeviceLinux* dev, bool null)
        if (!Null)\r
        {\r
 #ifdef _IRR_LINUX_X11_XINPUT2_\r
-               XIGetClientPointer(Device->XDisplay, Device->XWindow, &DeviceId);\r
+               // XIWarpPointer is entirely broken on multi-head setups (see also [1]),\r
+               // but behaves better in other cases so we can't just disable it outright.\r
+               // [1] https://developer.blender.org/rB165caafb99c6846e53d11c4e966990aaffc06cea\r
+               if (XScreenCount(Device->XDisplay) > 1)\r
+               {\r
+                       os::Printer::log("Detected classic multi-head setup, not using XIWarpPointer");\r
+               }\r
+               else\r
+               {\r
+                       XIGetClientPointer(Device->XDisplay, Device->XWindow, &DeviceId);\r
+               }\r
 #endif\r
 \r
                XGCValues values;\r