|
|
@@ -1,13 +1,14 @@
|
|
|
#include "common.h"
|
|
|
#include "CX11Output.h"
|
|
|
|
|
|
+#include <unistd.h>
|
|
|
#include <X11/Xlib.h>
|
|
|
#include <X11/Xatom.h>
|
|
|
#include <X11/extensions/Xrandr.h>
|
|
|
|
|
|
-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);
|
|
|
-}
|
|
|
+
|
|
|
+ // 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);
|
|
|
+}
|