diff --git a/CMakeLists.txt b/CMakeLists.txt index 0f96263..6b9f075 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -36,6 +36,8 @@ add_executable( wallengine main.cpp + src/WallpaperEngine/Assets/CPackageLoadException.cpp + src/WallpaperEngine/Assets/CPackageLoadException.h src/WallpaperEngine/Assets/CAssetLoadException.cpp src/WallpaperEngine/Assets/CAssetLoadException.h src/WallpaperEngine/Assets/CContainer.h diff --git a/main.cpp b/main.cpp index ce971b9..2b1d1ea 100644 --- a/main.cpp +++ b/main.cpp @@ -6,25 +6,20 @@ #include #include #include -#include -#include #include #include -#include -#include - #include "WallpaperEngine/Core/CProject.h" #include "WallpaperEngine/Render/CWallpaper.h" #include "WallpaperEngine/Render/CContext.h" -#include "WallpaperEngine/Render/CScene.h" -#include "WallpaperEngine/Render/CVideo.h" #include "WallpaperEngine/Assets/CPackage.h" #include "WallpaperEngine/Assets/CDirectory.h" #include "WallpaperEngine/Assets/CCombinedContainer.h" +#include "WallpaperEngine/Assets/CPackageLoadException.h" float g_Time; +bool g_KeepRunning = true; using namespace WallpaperEngine::Core::Types; @@ -58,24 +53,9 @@ std::string stringPathFixes(const std::string& s) return std::move (str); } -void free_display_wallpaper(int sig) +void signalhandler(int sig) { - Display* display = XOpenDisplay (nullptr); - Window root = DefaultRootWindow(display); - // create a blank pm to reset compositors values, compositors will render as a blank X window. - Pixmap pm = XCreatePixmap(display, root, 1, 1, 1); - 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); - XFreePixmap(display, pm); - // set background to black. Only needed if no compositors are running - XSetWindowBackground(display, root, 0); - // sync changes before exiting - XClearWindow(display, root); - XFlush(display); - XCloseDisplay(display); - exit(sig); + g_KeepRunning = false; } int main (int argc, char* argv[]) @@ -132,9 +112,6 @@ int main (int argc, char* argv[]) } } - // increment the option index (useful for when no options were found) - // option_index ++; - if (path.empty () == true) { if (optind < argc && strlen (argv [optind]) > 0) @@ -169,13 +146,9 @@ int main (int argc, char* argv[]) // ensure the path has a trailing slash - // Attach signals for unexpected killing of program by user. We need to reset the - // screen otherwise the background will remain the last frame on sigterm or sigint. - if (!screens.empty()) - { - std::signal(SIGINT, free_display_wallpaper); - std::signal(SIGTERM, free_display_wallpaper); - } + // attach signals so if a stop is requested the X11 resources are freed and the program shutsdown gracefully + std::signal(SIGINT, signalhandler); + std::signal(SIGTERM, signalhandler); // first of all, initialize the window if (glfwInit () == GLFW_FALSE) @@ -192,10 +165,6 @@ int main (int argc, char* argv[]) glfwWindowHint (GLFW_CONTEXT_VERSION_MAJOR, 2); glfwWindowHint (GLFW_CONTEXT_VERSION_MINOR, 1); - // will hide the window if we are drawing to X - if (!screens.empty()) - glfwWindowHint(GLFW_VISIBLE, GLFW_FALSE); - auto containers = new WallpaperEngine::Assets::CCombinedContainer (); // update the used path with the full one @@ -213,7 +182,7 @@ int main (int argc, char* argv[]) containers->add (new WallpaperEngine::Assets::CPackage (scene_path)); std::cout << "Detected scene.pkg file at " << scene_path << ". Adding to list of searchable paths" << std::endl; } - catch(std::filesystem::filesystem_error ex) + catch (CPackageLoadException ex) { // ignore this error, the package file was not found std::cout << "No scene.pkg file found at " << path << ". Defaulting to normal folder storage" << std::endl; @@ -228,10 +197,6 @@ int main (int argc, char* argv[]) // add containers to the list containers->add (new WallpaperEngine::Assets::CDirectory ("./assets/")); - // parse the project.json file - auto project = WallpaperEngine::Core::CProject::fromFile ("project.json", containers); - WallpaperEngine::Render::CWallpaper* wallpaper; - // auto projection = project->getWallpaper ()->as ()->getOrthogonalProjection (); // create the window! // TODO: DO WE NEED TO PASS MONITOR HERE OR ANYTHING? @@ -245,9 +210,6 @@ int main (int argc, char* argv[]) return 2; } - // initialize inputs - CMouseInput* mouseInput = new CMouseInput (window); - glfwMakeContextCurrent (window); // TODO: FIGURE THESE OUT BASED ON THE SCREEN @@ -266,33 +228,17 @@ int main (int argc, char* argv[]) } // initialize custom context class - WallpaperEngine::Render::CContext* context = new WallpaperEngine::Render::CContext (screens); + WallpaperEngine::Render::CContext* context = new WallpaperEngine::Render::CContext (screens, window); // initialize mouse support - context->setMouse (mouseInput); + context->setMouse (new CMouseInput (window)); // set the default viewport context->setDefaultViewport ({0, 0, windowWidth, windowHeight}); - - if (project->getType () == "scene") - { - WallpaperEngine::Core::CScene* scene = project->getWallpaper ()->as (); - wallpaper = new WallpaperEngine::Render::CScene (scene, containers, context); - } - else if (project->getType () == "video") - { - // special steps, running a video needs a root directory change, files are not loaded from the container classes - // as they're streamed from disk - chdir (path.c_str ()); - - WallpaperEngine::Core::CVideo* video = project->getWallpaper ()->as (); - wallpaper = new WallpaperEngine::Render::CVideo (video, containers, context); - } - else - { - throw std::runtime_error ("Unsupported wallpaper type"); - } - + // parse the project.json file + auto project = WallpaperEngine::Core::CProject::fromFile ("project.json", containers); // ensure the context knows what wallpaper to render - context->setWallpaper (wallpaper); + context->setWallpaper ( + WallpaperEngine::Render::CWallpaper::fromWallpaper (project->getWallpaper (), containers, context) + ); if (shouldEnableAudio == true) { @@ -313,18 +259,9 @@ int main (int argc, char* argv[]) // TODO: FIGURE OUT THE REQUIRED INPUT MODE, AS SOME WALLPAPERS USE THINGS LIKE MOUSE POSITION // glfwSetInputMode (window, GLFW_STICKY_KEYS, GL_TRUE); - // enable depth text - glEnable (GL_DEPTH_TEST); - glDepthFunc (GL_LESS); + double startTime, endTime, minimumTime = 1.0 / maximumFPS; - // cull anything that doesn't look at the camera (might be useful to disable in the future) - glDisable (GL_CULL_FACE); - - double minimumTime = 1.0 / maximumFPS; - double startTime = 0.0; - double endTime = 0.0; - - while (glfwWindowShouldClose (window) == 0) + while (glfwWindowShouldClose (window) == 0 && g_KeepRunning == true) { // get the real framebuffer size glfwGetFramebufferSize (window, &windowWidth, &windowHeight); @@ -334,8 +271,6 @@ int main (int argc, char* argv[]) g_Time = (float) glfwGetTime (); // get the start time of the frame startTime = glfwGetTime (); - // update our inputs first - mouseInput->update (); // render the scene context->render (); // do buffer swapping @@ -350,6 +285,8 @@ int main (int argc, char* argv[]) usleep ((minimumTime - (endTime - startTime)) * CLOCKS_PER_SEC); } + // free context + delete context; // terminate gl glfwTerminate (); // terminate SDL diff --git a/src/WallpaperEngine/Assets/CPackage.cpp b/src/WallpaperEngine/Assets/CPackage.cpp index ae31ebe..acc1763 100644 --- a/src/WallpaperEngine/Assets/CPackage.cpp +++ b/src/WallpaperEngine/Assets/CPackage.cpp @@ -1,12 +1,8 @@ -// -// Created by almamu on 8/8/21. -// - #include "CPackage.h" #include "CAssetLoadException.h" +#include "CPackageLoadException.h" #include -#include using namespace WallpaperEngine::Assets; @@ -55,7 +51,7 @@ void CPackage::init () FILE* fp = fopen (this->m_path.c_str (), "rb+"); if (fp == nullptr) - throw std::filesystem::filesystem_error ("Cannot find package file", std::error_code()); + throw CPackageLoadException (this->m_path, std::to_string (errno)); // first validate header this->validateHeader (fp); diff --git a/src/WallpaperEngine/Assets/CPackageLoadException.cpp b/src/WallpaperEngine/Assets/CPackageLoadException.cpp new file mode 100644 index 0000000..bc2c59f --- /dev/null +++ b/src/WallpaperEngine/Assets/CPackageLoadException.cpp @@ -0,0 +1,13 @@ +#include "CPackageLoadException.h" + +using namespace WallpaperEngine::Assets; + +CPackageLoadException::CPackageLoadException(const std::string& filename, const std::string& extrainfo) + : m_message("Cannot load package " + filename + ": " + extrainfo) +{ +} + +const char *CPackageLoadException::what() const noexcept +{ + return this->m_message.c_str (); +} diff --git a/src/WallpaperEngine/Assets/CPackageLoadException.h b/src/WallpaperEngine/Assets/CPackageLoadException.h new file mode 100644 index 0000000..7632e84 --- /dev/null +++ b/src/WallpaperEngine/Assets/CPackageLoadException.h @@ -0,0 +1,17 @@ +#pragma once + +#include +#include + +namespace WallpaperEngine::Assets +{ + class CPackageLoadException : public std::exception + { + public: + CPackageLoadException(const std::string& message, const std::string& extrainfo = ""); + const char* what() const noexcept override; + + private: + std::string m_message; + }; +} \ No newline at end of file diff --git a/src/WallpaperEngine/Render/CContext.cpp b/src/WallpaperEngine/Render/CContext.cpp index 5228c98..f3fadb1 100644 --- a/src/WallpaperEngine/Render/CContext.cpp +++ b/src/WallpaperEngine/Render/CContext.cpp @@ -11,11 +11,12 @@ using namespace WallpaperEngine::Render; -CContext::CContext (std::vector screens) : +CContext::CContext (std::vector screens, GLFWwindow* window) : m_wallpaper (nullptr), m_screens (std::move (screens)), m_isRootWindow (m_screens.empty () == false), - m_defaultViewport ({0, 0, 1920, 1080}) + m_defaultViewport ({0, 0, 1920, 1080}), + m_window (window) { this->initializeViewports (); } @@ -25,6 +26,9 @@ 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); + this->m_display = XOpenDisplay (nullptr); int xrandr_result, xrandr_error; @@ -94,9 +98,18 @@ void CContext::initializeViewports () // 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 (DefaultRootWindow (display))); +CContext::~CContext() +{ + if (this->m_screens.empty () == false) + { + // free any used resource + XDestroyImage (this->m_image); + XFreeGC (this->m_display, this->m_gc); + XFreePixmap (this->m_display, this->m_pixmap); + XCloseDisplay (this->m_display); + } } void CContext::render () @@ -104,6 +117,9 @@ void CContext::render () if (this->m_wallpaper == nullptr) return; + // ensure mouse information is up to date before drawing any frame + this->m_mouse->update (); + if (this->m_viewports.empty () == false) { bool firstFrame = true; diff --git a/src/WallpaperEngine/Render/CContext.h b/src/WallpaperEngine/Render/CContext.h index 440cd9d..351a7b5 100644 --- a/src/WallpaperEngine/Render/CContext.h +++ b/src/WallpaperEngine/Render/CContext.h @@ -16,7 +16,8 @@ namespace WallpaperEngine::Render class CContext { public: - CContext (std::vector screens); + CContext (std::vector screens, GLFWwindow* window); + ~CContext (); void initializeViewports (); void render (); @@ -30,6 +31,7 @@ namespace WallpaperEngine::Render Pixmap m_pixmap; GC m_gc; XImage* m_image; + GLFWwindow* m_window; char* m_imageData; CFBO* m_fbo; std::vector m_screens; diff --git a/src/WallpaperEngine/Render/CWallpaper.cpp b/src/WallpaperEngine/Render/CWallpaper.cpp index 309795a..4f72e27 100644 --- a/src/WallpaperEngine/Render/CWallpaper.cpp +++ b/src/WallpaperEngine/Render/CWallpaper.cpp @@ -355,4 +355,14 @@ CFBO* CWallpaper::findFBO (const std::string& name) const CFBO* CWallpaper::getFBO () const { return this->m_sceneFBO; +} + +CWallpaper* CWallpaper::fromWallpaper (Core::CWallpaper* wallpaper, CContainer* containers, CContext* context) +{ + if (wallpaper->is () == true) + return new WallpaperEngine::Render::CScene (wallpaper->as (), containers, context); + else if (wallpaper->is () == true) + return new WallpaperEngine::Render::CVideo (wallpaper->as (), containers, context); + else + throw std::runtime_error ("Unsupported wallpaper type"); } \ No newline at end of file diff --git a/src/WallpaperEngine/Render/CWallpaper.h b/src/WallpaperEngine/Render/CWallpaper.h index 6604f3d..809e773 100644 --- a/src/WallpaperEngine/Render/CWallpaper.h +++ b/src/WallpaperEngine/Render/CWallpaper.h @@ -75,6 +75,7 @@ namespace WallpaperEngine::Render * Updates the texcoord used for drawing to the used framebuffer */ void updateTexCoord (GLfloat* texCoords, GLsizeiptr size) const; + /** * Updates the destination framebuffer for this wallpaper * @@ -82,6 +83,15 @@ namespace WallpaperEngine::Render */ void setDestinationFramebuffer (GLuint framebuffer); + /** + * Creates a new instance of CWallpaper based on the information provided by the read backgrounds + * + * @param wallpaper + * + * @return + */ + static CWallpaper* fromWallpaper (Core::CWallpaper* wallpaper, CContainer* containers, CContext* context); + protected: /** * Renders a frame of the wallpaper