|
|
@@ -25,27 +25,34 @@ void CContext::initializeViewports ()
|
|
|
if (this->m_isRootWindow == false || this->m_screens.empty () == true)
|
|
|
return;
|
|
|
|
|
|
- Display* display = XOpenDisplay (nullptr);
|
|
|
+ this->m_display = XOpenDisplay (nullptr);
|
|
|
|
|
|
int xrandr_result, xrandr_error;
|
|
|
|
|
|
- if (!XRRQueryExtension (display, &xrandr_result, &xrandr_error))
|
|
|
+ if (!XRRQueryExtension (this->m_display, &xrandr_result, &xrandr_error))
|
|
|
{
|
|
|
std::cerr << "XRandr is not present, cannot detect specified screens, running in window mode" << std::endl;
|
|
|
return;
|
|
|
}
|
|
|
|
|
|
- int fullWidth = DisplayWidth (display, DefaultScreen (display));
|
|
|
- int fullHeight = DisplayHeight (display, DefaultScreen (display));
|
|
|
- XRRScreenResources* screenResources = XRRGetScreenResources (display, DefaultRootWindow (display));
|
|
|
+ Window root = DefaultRootWindow (this->m_display);
|
|
|
+ int fullWidth = DisplayWidth (this->m_display, DefaultScreen (this->m_display));
|
|
|
+ int fullHeight = DisplayHeight (this->m_display, DefaultScreen (this->m_display));
|
|
|
+ XRRScreenResources* screenResources = XRRGetScreenResources (this->m_display, DefaultRootWindow (this->m_display));
|
|
|
|
|
|
// there are some situations where xrandr returns null (like screen not using the extension)
|
|
|
if (screenResources == nullptr)
|
|
|
return;
|
|
|
|
|
|
+ // create the pixmap and gc used for this display, most situations only have one "display"
|
|
|
+ this->m_pixmap = XCreatePixmap (this->m_display, DefaultRootWindow (this->m_display), fullWidth, fullHeight, 24);
|
|
|
+ this->m_gc = XCreateGC (this->m_display, this->m_pixmap, 0, nullptr);
|
|
|
+ // fill the whole pixmap with black for now
|
|
|
+ XFillRectangle (this->m_display, this->m_pixmap, this->m_gc, 0, 0, fullWidth, fullHeight);
|
|
|
+
|
|
|
for (int i = 0; i < screenResources->noutput; i ++)
|
|
|
{
|
|
|
- XRROutputInfo* info = XRRGetOutputInfo (display, screenResources, screenResources->outputs [i]);
|
|
|
+ XRROutputInfo* info = XRRGetOutputInfo (this->m_display, screenResources, screenResources->outputs [i]);
|
|
|
|
|
|
// there are some situations where xrandr returns null (like screen not using the extension)
|
|
|
if (info == nullptr)
|
|
|
@@ -58,11 +65,11 @@ void CContext::initializeViewports ()
|
|
|
{
|
|
|
if (info->connection == RR_Connected && strcmp (info->name, (*cur).c_str ()) == 0)
|
|
|
{
|
|
|
- XRRCrtcInfo* crtc = XRRGetCrtcInfo (display, screenResources, info->crtc);
|
|
|
+ XRRCrtcInfo* crtc = XRRGetCrtcInfo (this->m_display, screenResources, info->crtc);
|
|
|
|
|
|
std::cout << "Found requested screen: " << info->name << " -> " << crtc->x << "x" << crtc->y << ":" << crtc->width << "x" << crtc->height << std::endl;
|
|
|
|
|
|
- glm::vec4 viewport = {
|
|
|
+ glm::ivec4 viewport = {
|
|
|
crtc->x, fullHeight - (crtc->y + crtc->height), crtc->width, crtc->height
|
|
|
};
|
|
|
|
|
|
@@ -77,6 +84,17 @@ void CContext::initializeViewports ()
|
|
|
|
|
|
XRRFreeScreenResources (screenResources);
|
|
|
|
|
|
+ // create the fbo that will handle the screen
|
|
|
+ this->m_fbo = new CFBO("_sc_FullFrameBuffer", ITexture::TextureFormat::ARGB8888, 1.0, fullWidth, fullHeight, fullWidth, fullHeight);
|
|
|
+
|
|
|
+ // set the window background so the pixmap is drawn
|
|
|
+ XSetWindowBackgroundPixmap(this->m_display, root, this->m_pixmap);
|
|
|
+
|
|
|
+ this->m_imageData = new char [fullWidth * fullHeight * 4];
|
|
|
+
|
|
|
+ // create the image for X11 to be able to copy it over
|
|
|
+ this->m_image = XCreateImage (this->m_display, CopyFromParent, 24, ZPixmap, 0, this->m_imageData, fullWidth, fullHeight, 32, 0);
|
|
|
+
|
|
|
// Cause of issue for issue #59 origial issue
|
|
|
// glfwWindowHintPointer (GLFW_NATIVE_PARENT_HANDLE, reinterpret_cast <void*> (DefaultRootWindow (display)));
|
|
|
}
|
|
|
@@ -88,43 +106,40 @@ void CContext::render ()
|
|
|
|
|
|
if (this->m_viewports.empty () == false)
|
|
|
{
|
|
|
- static Display* display = XOpenDisplay (nullptr);
|
|
|
+ bool firstFrame = true;
|
|
|
+ bool renderFrame = true;
|
|
|
auto cur = this->m_viewports.begin ();
|
|
|
auto end = this->m_viewports.end ();
|
|
|
+ int fullWidth = DisplayWidth (this->m_display, DefaultScreen (this->m_display));
|
|
|
+ int fullHeight = DisplayHeight (this->m_display, DefaultScreen (this->m_display));
|
|
|
+ Window root = DefaultRootWindow (this->m_display);
|
|
|
|
|
|
- Window root = DefaultRootWindow(display);
|
|
|
- int windowWidth = 1920, windowHeight = 1080;
|
|
|
- int fullWidth = DisplayWidth (display, DefaultScreen (display));
|
|
|
- int fullHeight = DisplayHeight (display, DefaultScreen (display));
|
|
|
-
|
|
|
- Pixmap pm = XCreatePixmap(display, root, fullWidth, fullHeight, 24);
|
|
|
- GC gc = XCreateGC(display, pm, 0, NULL);
|
|
|
- XFillRectangle(display, pm, gc, 0, 0, fullWidth, fullHeight);
|
|
|
-
|
|
|
- char* image_data;
|
|
|
- image_data = new char[windowWidth*windowHeight*4];
|
|
|
-
|
|
|
- this->m_wallpaper->render (this->m_defaultViewport, true, image_data);
|
|
|
- XImage* image = XCreateImage(display, CopyFromParent, 24, ZPixmap, 0, (char *)image_data, windowWidth, windowHeight, 32, 0);
|
|
|
for (; cur != end; cur ++)
|
|
|
{
|
|
|
- XPutImage(display, pm, gc, image, 0, 0, (*cur).x, (*cur).y, windowWidth, windowHeight);
|
|
|
+ // render the background
|
|
|
+ this->m_wallpaper->render (*cur, renderFrame, firstFrame);
|
|
|
+ // scenes need to render a new frame for each viewport as they produce different results
|
|
|
+ // but videos should only be rendered once per group of viewports
|
|
|
+ firstFrame = false;
|
|
|
+ renderFrame = !this->m_wallpaper->is <CVideo> ();
|
|
|
}
|
|
|
|
|
|
- // _XROOTPMAP_ID & ESETROOT_PMAP_ID allow other programs (compositors) to
|
|
|
+ // read the full texture into the image
|
|
|
+ glReadPixels (0, 0, fullWidth, fullHeight, GL_BGRA, GL_UNSIGNED_BYTE, (void*) this->m_imageData);
|
|
|
+
|
|
|
+ // put the image back into the screen
|
|
|
+ XPutImage (this->m_display, this->m_pixmap, this->m_gc, this->m_image, 0, 0, 0, 0, fullWidth, fullHeight);
|
|
|
+
|
|
|
+ // _XROOTPMAP_ID & ESETROOT_PMAP_ID allow other programs (compositors) to
|
|
|
// edit the background. Without these, other programs will clear the screen.
|
|
|
- Atom prop_root = XInternAtom(display, "_XROOTPMAP_ID", False);
|
|
|
- Atom prop_esetroot = XInternAtom(display, "ESETROOT_PMAP_ID", False);
|
|
|
- XChangeProperty(display, root, prop_root, XA_PIXMAP, 32, PropModeReplace, (unsigned char *) &pm, 1);
|
|
|
- XChangeProperty(display, root, prop_esetroot, XA_PIXMAP, 32, PropModeReplace, (unsigned char *) &pm, 1);
|
|
|
-
|
|
|
- XSetWindowBackgroundPixmap(display, root, pm);
|
|
|
- XClearWindow(display, root);
|
|
|
- XFlush(display);
|
|
|
-
|
|
|
- XDestroyImage(image);
|
|
|
- XFreePixmap(display, pm);
|
|
|
- XFreeGC(display, gc);
|
|
|
+ // it also forces the compositor to refresh the background (tested with picom)
|
|
|
+ Atom prop_root = XInternAtom(this->m_display, "_XROOTPMAP_ID", False);
|
|
|
+ Atom prop_esetroot = XInternAtom(this->m_display, "ESETROOT_PMAP_ID", False);
|
|
|
+ XChangeProperty(this->m_display, root, prop_root, XA_PIXMAP, 32, PropModeReplace, (unsigned char *) &this->m_pixmap, 1);
|
|
|
+ XChangeProperty(this->m_display, root, prop_esetroot, XA_PIXMAP, 32, PropModeReplace, (unsigned char *) &this->m_pixmap, 1);
|
|
|
+
|
|
|
+ XClearWindow(this->m_display, root);
|
|
|
+ XFlush(this->m_display);
|
|
|
}
|
|
|
else
|
|
|
this->m_wallpaper->render (this->m_defaultViewport);
|
|
|
@@ -133,6 +148,22 @@ void CContext::render ()
|
|
|
void CContext::setWallpaper (CWallpaper* wallpaper)
|
|
|
{
|
|
|
this->m_wallpaper = wallpaper;
|
|
|
+
|
|
|
+ // update the wallpaper's texcoords based on the mode we're running
|
|
|
+ if (this->m_screens.empty () == false)
|
|
|
+ {
|
|
|
+ GLfloat texCoords [] = {
|
|
|
+ 0.0f, 1.0f,
|
|
|
+ 1.0f, 1.0f,
|
|
|
+ 0.0f, 0.0f,
|
|
|
+ 0.0f, 0.0f,
|
|
|
+ 1.0f, 1.0f,
|
|
|
+ 1.0f, 0.0f
|
|
|
+ };
|
|
|
+
|
|
|
+ this->m_wallpaper->updateTexCoord (texCoords, sizeof (texCoords));
|
|
|
+ this->m_wallpaper->setDestinationFramebuffer (this->m_fbo->getFramebuffer ());
|
|
|
+ }
|
|
|
}
|
|
|
|
|
|
void CContext::setDefaultViewport (glm::vec4 defaultViewport)
|