소스 검색

Handle XIO errors to keep the background running as much as possible, should fix #91

Signed-off-by: Alexis Maiquez <almamu@almamu.com>
Alexis Maiquez 4 년 전
부모
커밋
6808f31cd6
2개의 변경된 파일과 45개의 추가작업 그리고 7개의 파일을 삭제
  1. 5 5
      main.cpp
  2. 40 2
      src/WallpaperEngine/Render/CContext.cpp

+ 5 - 5
main.cpp

@@ -223,14 +223,14 @@ int main (int argc, char* argv[])
         return 4;
     }
 
-    if (assetsDir == "")
+    if (assetsDir.empty () == true)
     {
         char* home = getenv ("HOME");
 
         if (home == nullptr)
             throw std::runtime_error ("$HOME doesn't exist");
 
-        std::string homepath = "";
+        std::string homepath;
 
         error = validatePath (home, homepath);
 
@@ -255,9 +255,9 @@ int main (int argc, char* argv[])
             break;
         }
 
-        if (assetsDir == "")
+        if (assetsDir.empty () == true)
         {
-            int len = strlen (argv [0]) + 1;
+            unsigned long len = strlen (argv [0]) + 1;
             char* copy = new char[len];
 
             strncpy (copy, argv [0], len);
@@ -274,7 +274,7 @@ int main (int argc, char* argv[])
                 std::cout << "Found assets folder alongside the binary: " << assetsDir << std::endl;
             }
 
-            delete copy;
+            delete[] copy;
         }
     }
     else

+ 40 - 2
src/WallpaperEngine/Render/CContext.cpp

@@ -1,4 +1,6 @@
 #include <iostream>
+#include <unistd.h>
+
 #include <X11/Xlib.h>
 #include <X11/Xatom.h>
 #include <X11/extensions/Xrandr.h>
@@ -11,6 +13,34 @@
 
 using namespace WallpaperEngine::Render;
 
+void CustomXIOErrorExitHandler (Display* dsp, void* userdata)
+{
+    auto context = static_cast <CContext*> (userdata);
+
+#ifdef DEBUG
+    std::cerr << "Critical XServer error detected. Attempting to recover..." << std::endl;
+#endif /* DEBUG */
+
+    // refetch all the resources
+    context->initializeViewports ();
+}
+
+int CustomXErrorHandler (Display* dsp, XErrorEvent* event)
+{
+#ifdef DEBUG
+    std::cerr << "Detected X error" << std::endl;
+#endif /* DEBUG */
+    return 0;
+}
+
+int CustomXIOErrorHandler (Display* dsp)
+{
+#ifdef DEBUG
+    std::cerr << "Detected X IO error" << std::endl;
+#endif /* DEBUG */
+    return 0;
+}
+
 CContext::CContext (std::vector <std::string> screens, GLFWwindow* window) :
     m_wallpaper (nullptr),
     m_screens (std::move (screens)),
@@ -26,11 +56,16 @@ void CContext::initializeViewports ()
     if (this->m_isRootWindow == false || this->m_screens.empty () == true)
         return;
 
-    // hide the glfw window if the viewports are to be detected
-    glfwHideWindow (this->m_window);
+    // clear the viewports we're drawing to
+    this->m_viewports.clear ();
 
     this->m_display = XOpenDisplay (nullptr);
 
+    // set the error handling to try and recover from X disconnections
+    XSetIOErrorExitHandler (this->m_display, CustomXIOErrorExitHandler, this);
+    XSetErrorHandler (CustomXErrorHandler);
+    XSetIOErrorHandler (CustomXIOErrorHandler);
+
     int xrandr_result, xrandr_error;
 
     if (!XRRQueryExtension (this->m_display, &xrandr_result, &xrandr_error))
@@ -39,6 +74,9 @@ void CContext::initializeViewports ()
         return;
     }
 
+    // hide the glfw window if the viewports are to be detected
+    glfwHideWindow (this->m_window);
+
     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));