mirror of
https://github.com/Almamu/linux-wallpaperengine.git
synced 2025-07-13 21:02:34 +08:00
Added support for detecting full-screen windows on X11 output
Signed-off-by: Alexis Maiquez <almamu@almamu.com>
This commit is contained in:
parent
847cd56ddf
commit
6802511bb9
@ -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);
|
||||
}
|
||||
|
@ -36,5 +36,6 @@ namespace WallpaperEngine::Render::Drivers::Output
|
||||
char* m_imageData;
|
||||
XImage* m_image;
|
||||
CVideoDriver& m_driver;
|
||||
std::vector <ScreenInfo> m_screens;
|
||||
};
|
||||
}
|
Loading…
Reference in New Issue
Block a user