mirror of
https://github.com/Almamu/linux-wallpaperengine.git
synced 2025-09-14 13:56:48 +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 "common.h"
|
||||||
#include "CX11Output.h"
|
#include "CX11Output.h"
|
||||||
|
|
||||||
|
#include <unistd.h>
|
||||||
#include <X11/Xlib.h>
|
#include <X11/Xlib.h>
|
||||||
#include <X11/Xatom.h>
|
#include <X11/Xatom.h>
|
||||||
#include <X11/extensions/Xrandr.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)
|
void CustomXIOErrorExitHandler (Display* dsp, void* userdata)
|
||||||
{
|
{
|
||||||
@ -24,7 +25,7 @@ int CustomXErrorHandler (Display* dpy, XErrorEvent* event)
|
|||||||
sLog.debugerror ("Detected X error");
|
sLog.debugerror ("Detected X error");
|
||||||
|
|
||||||
// call the original handler so we can keep some information reporting
|
// call the original handler so we can keep some information reporting
|
||||||
originalErrorHandler (dpy, event);
|
// originalErrorHandler (dpy, event);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@ -40,13 +41,16 @@ CX11Output::CX11Output (CApplicationContext& context, CVideoDriver& driver) :
|
|||||||
COutput (context),
|
COutput (context),
|
||||||
m_driver (driver)
|
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 ();
|
this->loadScreenInfo ();
|
||||||
}
|
}
|
||||||
|
|
||||||
CX11Output::~CX11Output ()
|
CX11Output::~CX11Output ()
|
||||||
{
|
{
|
||||||
this->free ();
|
this->free ();
|
||||||
XCloseDisplay (this->m_display);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void CX11Output::reset ()
|
void CX11Output::reset ()
|
||||||
@ -64,6 +68,7 @@ void CX11Output::free ()
|
|||||||
XFreeGC (this->m_display, this->m_gc);
|
XFreeGC (this->m_display, this->m_gc);
|
||||||
XFreePixmap (this->m_display, this->m_pixmap);
|
XFreePixmap (this->m_display, this->m_pixmap);
|
||||||
delete this->m_imageData;
|
delete this->m_imageData;
|
||||||
|
XCloseDisplay (this->m_display);
|
||||||
}
|
}
|
||||||
|
|
||||||
void* CX11Output::getImageBuffer () const
|
void* CX11Output::getImageBuffer () const
|
||||||
@ -91,12 +96,11 @@ void CX11Output::loadScreenInfo ()
|
|||||||
// reset the viewports
|
// reset the viewports
|
||||||
this->m_viewports.clear ();
|
this->m_viewports.clear ();
|
||||||
|
|
||||||
|
this->m_display = XOpenDisplay (nullptr);
|
||||||
// set the error handling to try and recover from X disconnections
|
// set the error handling to try and recover from X disconnections
|
||||||
#ifdef HAVE_XSETIOERROREXITHANDLER
|
#ifdef HAVE_XSETIOERROREXITHANDLER
|
||||||
XSetIOErrorExitHandler (this->m_display, CustomXIOErrorExitHandler, this);
|
XSetIOErrorExitHandler (this->m_display, CustomXIOErrorExitHandler, this);
|
||||||
#endif /* HAVE_XSETIOERROREXITHANDLER */
|
#endif /* HAVE_XSETIOERROREXITHANDLER */
|
||||||
originalErrorHandler = XSetErrorHandler (CustomXErrorHandler);
|
|
||||||
XSetIOErrorHandler (CustomXIOErrorHandler);
|
|
||||||
|
|
||||||
int xrandr_result, xrandr_error;
|
int xrandr_result, xrandr_error;
|
||||||
|
|
||||||
@ -125,19 +129,27 @@ void CX11Output::loadScreenInfo ()
|
|||||||
if (info == nullptr || info->connection != RR_Connected)
|
if (info == nullptr || info->connection != RR_Connected)
|
||||||
continue;
|
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);
|
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},
|
sLog.out ("Found requested screen: ", info->name, " -> ", crtc->x, "x", crtc->y, ":", crtc->width, "x", crtc->height);
|
||||||
info->name
|
|
||||||
};
|
this->m_viewports[info->name] =
|
||||||
|
{
|
||||||
|
{crtc->x, crtc->y, crtc->width, crtc->height},
|
||||||
|
info->name
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
XRRFreeCrtcInfo (crtc);
|
XRRFreeCrtcInfo (crtc);
|
||||||
}
|
}
|
||||||
@ -174,4 +186,47 @@ void CX11Output::updateRender () const
|
|||||||
|
|
||||||
XClearWindow(this->m_display, this->m_root);
|
XClearWindow(this->m_display, this->m_root);
|
||||||
XFlush(this->m_display);
|
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;
|
char* m_imageData;
|
||||||
XImage* m_image;
|
XImage* m_image;
|
||||||
CVideoDriver& m_driver;
|
CVideoDriver& m_driver;
|
||||||
|
std::vector <ScreenInfo> m_screens;
|
||||||
};
|
};
|
||||||
}
|
}
|
Loading…
Reference in New Issue
Block a user