Added support for detecting full-screen windows on X11 output

Signed-off-by: Alexis Maiquez <almamu@almamu.com>
This commit is contained in:
Alexis Maiquez 2023-03-21 23:41:46 +01:00
parent 847cd56ddf
commit 6802511bb9
2 changed files with 73 additions and 17 deletions

View File

@ -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);
}

View File

@ -36,5 +36,6 @@ namespace WallpaperEngine::Render::Drivers::Output
char* m_imageData;
XImage* m_image;
CVideoDriver& m_driver;
std::vector <ScreenInfo> m_screens;
};
}