diff --git a/src/WallpaperEngine/Render/Drivers/Output/CX11Output.cpp b/src/WallpaperEngine/Render/Drivers/Output/CX11Output.cpp index 530d803..3fb059c 100644 --- a/src/WallpaperEngine/Render/Drivers/Output/CX11Output.cpp +++ b/src/WallpaperEngine/Render/Drivers/Output/CX11Output.cpp @@ -1,13 +1,14 @@ #include "common.h" #include "CX11Output.h" +#include #include #include #include -using namespace WallpaperEngine::Render::Drivers::Output; +#define FULLSCREEN_CHECK_WAIT_TIME 250 -XErrorHandler originalErrorHandler; +using namespace WallpaperEngine::Render::Drivers::Output; void CustomXIOErrorExitHandler (Display* dsp, void* userdata) { @@ -24,7 +25,7 @@ int CustomXErrorHandler (Display* dpy, XErrorEvent* event) sLog.debugerror ("Detected X error"); // call the original handler so we can keep some information reporting - originalErrorHandler (dpy, event); + // originalErrorHandler (dpy, event); return 0; } @@ -40,13 +41,16 @@ CX11Output::CX11Output (CApplicationContext& context, CVideoDriver& driver) : COutput (context), m_driver (driver) { - this->m_display = XOpenDisplay (nullptr); + // do not use previous handler, it might stop the app under weird circumstances + XSetErrorHandler (CustomXErrorHandler); + XSetIOErrorHandler (CustomXIOErrorHandler); + this->loadScreenInfo (); } + CX11Output::~CX11Output () { this->free (); - XCloseDisplay (this->m_display); } void CX11Output::reset () @@ -64,6 +68,7 @@ void CX11Output::free () XFreeGC (this->m_display, this->m_gc); XFreePixmap (this->m_display, this->m_pixmap); delete this->m_imageData; + XCloseDisplay (this->m_display); } void* CX11Output::getImageBuffer () const @@ -91,12 +96,11 @@ void CX11Output::loadScreenInfo () // reset the viewports this->m_viewports.clear (); + this->m_display = XOpenDisplay (nullptr); // set the error handling to try and recover from X disconnections #ifdef HAVE_XSETIOERROREXITHANDLER XSetIOErrorExitHandler (this->m_display, CustomXIOErrorExitHandler, this); #endif /* HAVE_XSETIOERROREXITHANDLER */ - originalErrorHandler = XSetErrorHandler (CustomXErrorHandler); - XSetIOErrorHandler (CustomXIOErrorHandler); int xrandr_result, xrandr_error; @@ -125,19 +129,27 @@ void CX11Output::loadScreenInfo () if (info == nullptr || info->connection != RR_Connected) continue; - // only keep info of registered screens - if (this->m_context.screenSettings.find (info->name) == this->m_context.screenSettings.end ()) - continue; - XRRCrtcInfo* crtc = XRRGetCrtcInfo (this->m_display, screenResources, info->crtc); - sLog.out ("Found requested screen: ", info->name, " -> ", crtc->x, "x", crtc->y, ":", crtc->width, "x", crtc->height); + // add the screen to the list of screens + this->m_screens.push_back ( + { + {crtc->x, crtc->y, crtc->width, crtc->height}, + info->name + } + ); - this->m_viewports [info->name] = + // only keep info of registered screens + if (this->m_context.screenSettings.find (info->name) != this->m_context.screenSettings.end ()) { - {crtc->x, crtc->y, crtc->width, crtc->height}, - info->name - }; + sLog.out ("Found requested screen: ", info->name, " -> ", crtc->x, "x", crtc->y, ":", crtc->width, "x", crtc->height); + + this->m_viewports[info->name] = + { + {crtc->x, crtc->y, crtc->width, crtc->height}, + info->name + }; + } XRRFreeCrtcInfo (crtc); } @@ -174,4 +186,47 @@ void CX11Output::updateRender () const XClearWindow(this->m_display, this->m_root); XFlush(this->m_display); -} \ No newline at end of file + + // stop rendering if anything is fullscreen + bool isFullscreen = false; + XWindowAttributes attribs; + Window _; + Window* children; + unsigned int nchildren; + + do + { + isFullscreen = false; + + if (!XQueryTree (this->m_display, this->m_root, &_, &_, &children, &nchildren)) + return; + + for (int i = 0; i < nchildren; i++) + { + if (!XGetWindowAttributes (this->m_display, children [i], &attribs)) + continue; + + if (attribs.map_state != IsViewable) + continue; + + // compare width and height with the different screens we have + for (const auto& screen : this->m_screens) + { + if ( + attribs.x == screen.viewport.x && attribs.y == screen.viewport.y && + attribs.width == screen.viewport.z && attribs.height == screen.viewport.w + ) + { + isFullscreen = true; + break; + } + } + } + + XFree (children); + + // give the cpu some time to check again later + usleep (FULLSCREEN_CHECK_WAIT_TIME); + } + while (isFullscreen); +} diff --git a/src/WallpaperEngine/Render/Drivers/Output/CX11Output.h b/src/WallpaperEngine/Render/Drivers/Output/CX11Output.h index 5ef8218..2759847 100644 --- a/src/WallpaperEngine/Render/Drivers/Output/CX11Output.h +++ b/src/WallpaperEngine/Render/Drivers/Output/CX11Output.h @@ -36,5 +36,6 @@ namespace WallpaperEngine::Render::Drivers::Output char* m_imageData; XImage* m_image; CVideoDriver& m_driver; + std::vector m_screens; }; } \ No newline at end of file