CContext.cpp 4.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150
  1. #include <iostream>
  2. #include <X11/Xlib.h>
  3. #include <X11/Xatom.h>
  4. #include <X11/extensions/Xrandr.h>
  5. #include <GL/glew.h>
  6. #include <GL/glx.h>
  7. #include "CContext.h"
  8. #include "CVideo.h"
  9. using namespace WallpaperEngine::Render;
  10. CContext::CContext (std::vector <std::string> screens) :
  11. m_wallpaper (nullptr),
  12. m_screens (std::move (screens)),
  13. m_isRootWindow (m_screens.empty () == false),
  14. m_defaultViewport ({0, 0, 1920, 1080})
  15. {
  16. this->initializeViewports ();
  17. }
  18. void CContext::initializeViewports ()
  19. {
  20. if (this->m_isRootWindow == false || this->m_screens.empty () == true)
  21. return;
  22. Display* display = XOpenDisplay (nullptr);
  23. int xrandr_result, xrandr_error;
  24. if (!XRRQueryExtension (display, &xrandr_result, &xrandr_error))
  25. {
  26. std::cerr << "XRandr is not present, cannot detect specified screens, running in window mode" << std::endl;
  27. return;
  28. }
  29. int fullWidth = DisplayWidth (display, DefaultScreen (display));
  30. int fullHeight = DisplayHeight (display, DefaultScreen (display));
  31. XRRScreenResources* screenResources = XRRGetScreenResources (display, DefaultRootWindow (display));
  32. // there are some situations where xrandr returns null (like screen not using the extension)
  33. if (screenResources == nullptr)
  34. return;
  35. for (int i = 0; i < screenResources->noutput; i ++)
  36. {
  37. XRROutputInfo* info = XRRGetOutputInfo (display, screenResources, screenResources->outputs [i]);
  38. // there are some situations where xrandr returns null (like screen not using the extension)
  39. if (info == nullptr)
  40. continue;
  41. auto cur = this->m_screens.begin ();
  42. auto end = this->m_screens.end ();
  43. for (; cur != end; cur ++)
  44. {
  45. if (info->connection == RR_Connected && strcmp (info->name, (*cur).c_str ()) == 0)
  46. {
  47. XRRCrtcInfo* crtc = XRRGetCrtcInfo (display, screenResources, info->crtc);
  48. std::cout << "Found requested screen: " << info->name << " -> " << crtc->x << "x" << crtc->y << ":" << crtc->width << "x" << crtc->height << std::endl;
  49. glm::vec4 viewport = {
  50. crtc->x, fullHeight - (crtc->y + crtc->height), crtc->width, crtc->height
  51. };
  52. this->m_viewports.push_back (viewport);
  53. XRRFreeCrtcInfo (crtc);
  54. }
  55. }
  56. XRRFreeOutputInfo (info);
  57. }
  58. XRRFreeScreenResources (screenResources);
  59. // Cause of issue for issue #59 origial issue
  60. // glfwWindowHintPointer (GLFW_NATIVE_PARENT_HANDLE, reinterpret_cast <void*> (DefaultRootWindow (display)));
  61. }
  62. void CContext::render ()
  63. {
  64. if (this->m_wallpaper == nullptr)
  65. return;
  66. if (this->m_viewports.empty () == false)
  67. {
  68. static Display* display = XOpenDisplay (nullptr);
  69. bool firstFrame = true;
  70. bool renderFrame = true;
  71. auto cur = this->m_viewports.begin ();
  72. auto end = this->m_viewports.end ();
  73. Window root = DefaultRootWindow(display);
  74. int windowWidth = 1920, windowHeight = 1080;
  75. int fullWidth = DisplayWidth (display, DefaultScreen (display));
  76. int fullHeight = DisplayHeight (display, DefaultScreen (display));
  77. Pixmap pm = XCreatePixmap(display, root, fullWidth, fullHeight, 24);
  78. GC gc = XCreateGC(display, pm, 0, NULL);
  79. XFillRectangle(display, pm, gc, 0, 0, fullWidth, fullHeight);
  80. char* image_data = this->m_wallpaper->renderImage (*cur, renderFrame, firstFrame);
  81. XImage* image = XCreateImage(display, CopyFromParent, 24, ZPixmap, 0, (char *)image_data, windowWidth, windowHeight, 32, 0);
  82. for (; cur != end; cur ++)
  83. {
  84. XPutImage(display, pm, gc, image, 0, 0, (*cur).x, (*cur).y, windowWidth, windowHeight);
  85. }
  86. // _XROOTPMAP_ID & ESETROOT_PMAP_ID allow other programs (compositors) to
  87. // edit the background. Without these, other programs will clear the screen.
  88. Atom prop_root = XInternAtom(display, "_XROOTPMAP_ID", False);
  89. Atom prop_esetroot = XInternAtom(display, "ESETROOT_PMAP_ID", False);
  90. XChangeProperty(display, root, prop_root, XA_PIXMAP, 32, PropModeReplace, (unsigned char *) &pm, 1);
  91. XChangeProperty(display, root, prop_esetroot, XA_PIXMAP, 32, PropModeReplace, (unsigned char *) &pm, 1);
  92. XSetWindowBackgroundPixmap(display, root, pm);
  93. XClearWindow(display, root);
  94. XFlush(display);
  95. XDestroyImage(image);
  96. XFreePixmap(display, pm);
  97. XFreeGC(display, gc);
  98. }
  99. else
  100. this->m_wallpaper->render (this->m_defaultViewport);
  101. }
  102. void CContext::setWallpaper (CWallpaper* wallpaper)
  103. {
  104. this->m_wallpaper = wallpaper;
  105. }
  106. void CContext::setDefaultViewport (glm::vec4 defaultViewport)
  107. {
  108. this->m_defaultViewport = defaultViewport;
  109. }
  110. CMouseInput* CContext::getMouse () const
  111. {
  112. return this->m_mouse;
  113. }
  114. void CContext::setMouse (CMouseInput* mouse)
  115. {
  116. this->m_mouse = mouse;
  117. }