Explorar o código

Merge branch 'data-separation' of https://github.com/Almamu/linux-wallpaperengine into data-separation

# Conflicts:
#	main.cpp
#	src/WallpaperEngine/video/renderer.cpp

Signed-off-by: Alexis Maiquez <almamu@almamu.com>
Alexis Maiquez %!s(int64=7) %!d(string=hai) anos
pai
achega
75fd581eac
Modificáronse 5 ficheiros con 180 adicións e 23 borrados
  1. 3 2
      CMakeLists.txt
  2. 78 0
      CMakeModules/FindXrandr.cmake
  3. 10 0
      README.md
  4. 86 19
      main.cpp
  5. 3 2
      src/WallpaperEngine/video/renderer.cpp

+ 3 - 2
CMakeLists.txt

@@ -7,6 +7,7 @@ set(CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/CMakeModules")
 set(OpenGL_GL_PREFERENCE "LEGACY")
 set(OpenGL_GL_PREFERENCE "LEGACY")
 
 
 find_package(X11 REQUIRED)
 find_package(X11 REQUIRED)
+find_package(Xrandr REQUIRED)
 find_package(OpenGL REQUIRED)
 find_package(OpenGL REQUIRED)
 find_package(GLUT REQUIRED)
 find_package(GLUT REQUIRED)
 find_package(ZLIB REQUIRED)
 find_package(ZLIB REQUIRED)
@@ -15,7 +16,7 @@ find_package(SDL REQUIRED)
 find_package(SDL_mixer REQUIRED)
 find_package(SDL_mixer REQUIRED)
 find_package(LZ4 REQUIRED)
 find_package(LZ4 REQUIRED)
 
 
-include_directories(${X11_INCLUDE_DIR} ${IRRLICHT_INCLUDE_DIR} ${LZ4_INCLUDE_DIR} ${SDL_INCLUDE_DIRS} ${SDL_MIXER_INCLUDE_DIRS} src include)
+include_directories(${X11_INCLUDE_DIR} ${XRANDR_INCLUDE_DIR} ${IRRLICHT_INCLUDE_DIR} ${LZ4_INCLUDE_DIR} ${SDL_INCLUDE_DIRS} ${SDL_MIXER_INCLUDE_DIRS} src include)
 
 
 add_executable(
 add_executable(
         wallengine
         wallengine
@@ -114,4 +115,4 @@ add_executable(
         src/WallpaperEngine/Core/Objects/Images/Materials/CPassess.h
         src/WallpaperEngine/Core/Objects/Images/Materials/CPassess.h
 )
 )
 
 
-target_link_libraries(wallengine ${X11_LIBRARIES} ${X11_Xxf86vm_LIB} ${OPENGL_LIBRARIES} ${GLUT_LIBRARIES} ${ZLIB_LIBRARIES} ${IRRLICHT_LIBRARY} ${LZ4_LIBRARY} ${SDL_LIBRARY} ${SDL_MIXER_LIBRARIES})
+target_link_libraries(wallengine ${X11_LIBRARIES} ${XRANDR_LIBRARIES} ${X11_Xxf86vm_LIB} ${OPENGL_LIBRARIES} ${GLUT_LIBRARIES} ${ZLIB_LIBRARIES} ${IRRLICHT_LIBRARY} ${LZ4_LIBRARY} ${SDL_LIBRARY} ${SDL_MIXER_LIBRARIES})

+ 78 - 0
CMakeModules/FindXrandr.cmake

@@ -0,0 +1,78 @@
+# - try to find the Xrandr library
+#
+# Cache Variables: (probably not for direct use in your scripts)
+#  XRANDR_INCLUDE_DIR
+#  XRANDR_SOURCE_DIR
+#  XRANDR_LIBRARY
+#
+# Non-cache variables you might use in your CMakeLists.txt:
+#  XRANDR_FOUND
+#  XRANDR_INCLUDE_DIRS
+#  XRANDR_LIBRARIES
+#
+# Requires these CMake modules:
+#  FindPackageHandleStandardArgs (known included with CMake >=2.6.2)
+#
+# Original Author:
+# 2014 Kevin M. Godby <kevin@godby.org>
+#
+# Distributed under the Boost Software License, Version 1.0.
+# (See accompanying file LICENSE_1_0.txt or copy at
+# http://www.boost.org/LICENSE_1_0.txt)
+
+set(XRANDR_ROOT_DIR
+        "${XRANDR_ROOT_DIR}"
+        CACHE
+        PATH
+        "Directory to search for Xrandr")
+
+find_package(PkgConfig QUIET)
+if(PKG_CONFIG_FOUND)
+    pkg_check_modules(PC_LIBXRANDR xrandr)
+endif()
+
+find_library(XRANDR_LIBRARY
+        NAMES
+        Xrandr
+        PATHS
+        ${PC_LIBXRANDR_LIBRARY_DIRS}
+        ${PC_LIBXRANDR_LIBDIR}
+        HINTS
+        "${XRANDR_ROOT_DIR}"
+        PATH_SUFFIXES
+        lib
+        )
+
+get_filename_component(_libdir "${XRANDR_LIBRARY}" PATH)
+
+find_path(XRANDR_INCLUDE_DIR
+        NAMES
+        Xrandr.h
+        PATHS
+        ${PC_LIBXRANDR_INCLUDE_DIRS}
+        ${PC_LIBXRANDR_INCLUDEDIR}
+        HINTS
+        "${_libdir}"
+        "${_libdir}/.."
+        "${XRANDR_ROOT_DIR}"
+        PATH_SUFFIXES
+        X11
+        X11/extensions
+        )
+
+include(FindPackageHandleStandardArgs)
+find_package_handle_standard_args(XRANDR
+        DEFAULT_MSG
+        XRANDR_LIBRARY
+        XRANDR_INCLUDE_DIR
+        )
+
+if(XRANDR_FOUND)
+    list(APPEND XRANDR_LIBRARIES ${XRANDR_LIBRARY})
+    list(APPEND XRANDR_INCLUDE_DIRS ${XRANDR_INCLUDE_DIR})
+    mark_as_advanced(XRANDR_ROOT_DIR)
+endif()
+
+mark_as_advanced(XRANDR_INCLUDE_DIR
+        XRANDR_LIBRARY)
+

+ 10 - 0
README.md

@@ -15,6 +15,8 @@ Wallpaper Engine is a software designed by [Kristjan Skutta](https://store.steam
 - ZLIB
 - ZLIB
 - SDL
 - SDL
 - SDL_mixer
 - SDL_mixer
+- X11
+- Xrandr
 
 
 # 5. How to use
 # 5. How to use
 ## 5.1. Pre-requirements
 ## 5.1. Pre-requirements
@@ -68,6 +70,14 @@ Uncompressed backgrounds are just plain folders including all the resources and
 ./wallengine --dir folder
 ./wallengine --dir folder
 ```
 ```
 
 
+#### 5.4.3. Running as a screen's background
+Only screens configured with the XRandr extension are supported. To specify the screen names (as reported from xrandr tool) just use the ```--screen-root``` switch. You can specify multiple screens at the same time, for example:
+```
+./wallengine --screen-root HDMI-1 --screen-root DVI-D-1
+```
+
+**IMPORTANT: Right now this doesn't work if there is anything drawing to the background (like a compositor, nautilus, etc)**
+
 ###### Example background
 ###### Example background
 This was the first background to even be compatible with the software. And It's not 100% compatible yet. Both textures and shaders are properly loaded, but there are still particles missing.
 This was the first background to even be compatible with the software. And It's not 100% compatible yet. Both textures and shaders are properly loaded, but there are still particles missing.
 
 

+ 86 - 19
main.cpp

@@ -9,6 +9,7 @@
 #include <SDL.h>
 #include <SDL.h>
 
 
 #include <X11/Xlib.h>
 #include <X11/Xlib.h>
+#include <X11/extensions/Xrandr.h>
 
 
 #include "WallpaperEngine/Render/Shaders/Compiler.h"
 #include "WallpaperEngine/Render/Shaders/Compiler.h"
 #include "WallpaperEngine/project.h"
 #include "WallpaperEngine/project.h"
@@ -17,12 +18,74 @@
 #include "WallpaperEngine/Core/CProject.h"
 #include "WallpaperEngine/Core/CProject.h"
 #include "WallpaperEngine/Irrlicht/CContext.h"
 #include "WallpaperEngine/Irrlicht/CContext.h"
 
 
-int WinID = 0;
+bool IsRootWindow = false;
+std::vector<std::string> Screens;
+std::vector<irr::core::rect<irr::s32>> Viewports;
+
 irr::SIrrlichtCreationParameters _irr_params;
 irr::SIrrlichtCreationParameters _irr_params;
 
 
 irr::f32 g_Time = 0;
 irr::f32 g_Time = 0;
 
 
 WallpaperEngine::Irrlicht::CContext* IrrlichtContext;
 WallpaperEngine::Irrlicht::CContext* IrrlichtContext;
+void initialize_viewports ()
+{
+    if (IsRootWindow == false || Screens.size () == 0)
+        return;
+
+    Display* display = XOpenDisplay (NULL);
+    int xrandr_result, xrandr_error;
+
+    if (!XRRQueryExtension (display, &xrandr_result, &xrandr_error))
+    {
+        std::cerr << "XRandr is not present, cannot detect specified screens, running in window mode" << std::endl;
+        return;
+    }
+
+    XRRScreenResources* screenResources = XRRGetScreenResources (display, DefaultRootWindow (display));
+
+    // there are some situations where xrandr returns null (like screen not using the extension)
+    if (screenResources == nullptr)
+        return;
+
+    for (int i = 0; i < screenResources->noutput; i ++)
+    {
+        XRROutputInfo* info = XRRGetOutputInfo (display, screenResources, screenResources->outputs [i]);
+
+        // there are some situations where xrandr returns null (like screen not using the extension)
+        if (info == nullptr)
+            continue;
+
+        std::vector<std::string>::iterator cur = Screens.begin ();
+        std::vector<std::string>::iterator end = Screens.end ();
+
+        for (; cur != end; cur ++)
+        {
+            if (info->connection == RR_Connected && strcmp (info->name, (*cur).c_str ()) == 0)
+            {
+                XRRCrtcInfo* crtc = XRRGetCrtcInfo (display, screenResources, info->crtc);
+
+                std::cout << "Found requested screen: " << info->name << " -> " << crtc->x << "x" << crtc->y << ":" << crtc->width << "x" << crtc->height << std::endl;
+
+                irr::core::rect<irr::s32> viewport;
+
+                viewport.UpperLeftCorner.X = crtc->x;
+                viewport.UpperLeftCorner.Y = crtc->y;
+                viewport.LowerRightCorner.X = crtc->x + crtc->width;
+                viewport.LowerRightCorner.Y = crtc->y + crtc->height;
+
+                Viewports.push_back (viewport);
+
+                XRRFreeCrtcInfo (crtc);
+            }
+        }
+
+        XRRFreeOutputInfo (info);
+    }
+
+    XRRFreeScreenResources (screenResources);
+
+    _irr_params.WindowId = reinterpret_cast<void*> (DefaultRootWindow (display));
+}
 
 
 int init_irrlicht()
 int init_irrlicht()
 {
 {
@@ -33,7 +96,7 @@ int init_irrlicht()
     _irr_params.Bits = 16;
     _irr_params.Bits = 16;
     // _irr_params.DeviceType = Irrlicht::EIDT_X11;
     // _irr_params.DeviceType = Irrlicht::EIDT_X11;
     _irr_params.DriverType = irr::video::EDT_OPENGL;
     _irr_params.DriverType = irr::video::EDT_OPENGL;
-    _irr_params.Doublebuffer = true;
+    _irr_params.Doublebuffer = false;
     _irr_params.EventReceiver = nullptr;
     _irr_params.EventReceiver = nullptr;
     _irr_params.Fullscreen = false;
     _irr_params.Fullscreen = false;
     _irr_params.HandleSRGB = false;
     _irr_params.HandleSRGB = false;
@@ -45,10 +108,7 @@ int init_irrlicht()
     _irr_params.ZBufferBits = 24;
     _irr_params.ZBufferBits = 24;
     _irr_params.LoggingLevel = irr::ELL_DEBUG;
     _irr_params.LoggingLevel = irr::ELL_DEBUG;
 
 
-    Display* display = XOpenDisplay (NULL);
-    int screen = XDefaultScreen (display);
-
-    _irr_params.WindowId = reinterpret_cast<void*> (XRootWindow (display, screen));
+    initialize_viewports ();
 
 
     IrrlichtContext->setDevice (irr::createDeviceEx (_irr_params));
     IrrlichtContext->setDevice (irr::createDeviceEx (_irr_params));
 
 
@@ -99,7 +159,7 @@ void print_help (const char* route)
         << "  --silent\t\tMutes all the sound the wallpaper might produce" << std::endl
         << "  --silent\t\tMutes all the sound the wallpaper might produce" << std::endl
         << "  --dir <folder>\tLoads an uncompressed background from the given <folder>" << std::endl
         << "  --dir <folder>\tLoads an uncompressed background from the given <folder>" << std::endl
         << "  --pkg <folder>\tLoads a scene.pkg file from the given <folder>" << std::endl
         << "  --pkg <folder>\tLoads a scene.pkg file from the given <folder>" << std::endl
-        << "  --win <WindowID>\tX Window ID to attach to" << std::endl;
+        << "  --screen-root <screen name>\tDisplay as screen's background" << std::endl;
 }
 }
 
 
 std::string stringPathFixes(const std::string& s){
 std::string stringPathFixes(const std::string& s){
@@ -124,26 +184,26 @@ int main (int argc, char* argv[])
     int option_index = 0;
     int option_index = 0;
 
 
     static struct option long_options [] = {
     static struct option long_options [] = {
-            {"win",     required_argument, 0, 'w'},
-            {"pkg",     required_argument, 0, 'p'},
-            {"dir",     required_argument, 0, 'd'},
-            {"silent",  optional_argument, 0, 's'},
-            {"help",    optional_argument, 0, 'h'},
+            {"screen-root", required_argument, 0, 'r'},
+            {"pkg",         required_argument, 0, 'p'},
+            {"dir",         required_argument, 0, 'd'},
+            {"silent",      optional_argument, 0, 's'},
+            {"help",        optional_argument, 0, 'h'},
             {nullptr,                   0, 0,   0}
             {nullptr,                   0, 0,   0}
     };
     };
 
 
     while (true)
     while (true)
     {
     {
-        int c = getopt_long (argc, argv, "w:p:d:sh", long_options, &option_index);
+        int c = getopt_long (argc, argv, "r:p:d:sh", long_options, &option_index);
 
 
         if (c == -1)
         if (c == -1)
             break;
             break;
 
 
         switch (c)
         switch (c)
         {
         {
-            case 'w':
-                if (optarg)
-                    WinID = atoi (optarg);
+            case 'r':
+                IsRootWindow = true;
+                Screens.push_back (optarg);
                 break;
                 break;
 
 
             case 'p':
             case 'p':
@@ -169,8 +229,6 @@ int main (int argc, char* argv[])
         }
         }
     }
     }
 
 
-    std::cout << "Initializing irrlicht to WindowID " << WinID << std::endl;
-
     if (init_irrlicht ())
     if (init_irrlicht ())
     {
     {
         return 1;
         return 1;
@@ -257,7 +315,16 @@ int main (int argc, char* argv[])
 
 
             if (currentTime - lastTime > minimumTime)
             if (currentTime - lastTime > minimumTime)
             {
             {
-                WallpaperEngine::video::renderer::render ();
+                std::vector<irr::core::rect<irr::s32>>::iterator cur = Viewports.begin ();
+                std::vector<irr::core::rect<irr::s32>>::iterator end = Viewports.end ();
+
+                for (; cur != end; cur ++)
+                {
+                    // change viewport to render to the correct portion of the display
+                    IrrlichtContext->getDevice ()->getVideoDriver ()->setViewPort (*cur);
+                    WallpaperEngine::video::renderer::render ();
+                }
+
                 lastTime = currentTime;
                 lastTime = currentTime;
             }
             }
             else
             else

+ 3 - 2
src/WallpaperEngine/video/renderer.cpp

@@ -43,9 +43,10 @@ namespace WallpaperEngine
 
 
         void renderer::render ()
         void renderer::render ()
         {
         {
-            if (IrrlichtContext->getDevice ()->getVideoDriver () == nullptr) return;
+            if (IrrlichtContext->getDevice ()->getVideoDriver () == nullptr)
+                return;
 
 
-            IrrlichtContext->getDevice ()->getVideoDriver ()->beginScene(true, true, irr::video::SColor(0, 0, 0, 0));
+            IrrlichtContext->getDevice ()->getVideoDriver ()->beginScene(false, true, irr::video::SColor(0, 0, 0, 0));
 
 
             std::vector<node*>::const_iterator cur = s_nodes.begin ();
             std::vector<node*>::const_iterator cur = s_nodes.begin ();
             std::vector<node*>::const_iterator end = s_nodes.end ();
             std::vector<node*>::const_iterator end = s_nodes.end ();