Jelajahi Sumber

~ Support for displaying on background of specific screens instead of displaying on top, please carefuly read the README.md before using

Signed-off-by: Alexis Maiquez <almamu@almamu.com>
Alexis Maiquez 7 tahun lalu
induk
melakukan
82c187fa76
6 mengubah file dengan 170 tambahan dan 48 penghapusan
  1. 0 29
      .idea/codeStyles/Project.xml
  2. 3 2
      CMakeLists.txt
  3. 78 0
      CMakeModules/FindXrandr.cmake
  4. 10 0
      README.md
  5. 78 16
      main.cpp
  6. 1 1
      wallpaperengine/video/renderer.cpp

+ 0 - 29
.idea/codeStyles/Project.xml

@@ -1,29 +0,0 @@
-<component name="ProjectCodeStyleConfiguration">
-  <code_scheme name="Project" version="173">
-    <Objective-C-extensions>
-      <file>
-        <option name="com.jetbrains.cidr.lang.util.OCDeclarationKind" value="Import" />
-        <option name="com.jetbrains.cidr.lang.util.OCDeclarationKind" value="Macro" />
-        <option name="com.jetbrains.cidr.lang.util.OCDeclarationKind" value="Typedef" />
-        <option name="com.jetbrains.cidr.lang.util.OCDeclarationKind" value="Enum" />
-        <option name="com.jetbrains.cidr.lang.util.OCDeclarationKind" value="Constant" />
-        <option name="com.jetbrains.cidr.lang.util.OCDeclarationKind" value="Global" />
-        <option name="com.jetbrains.cidr.lang.util.OCDeclarationKind" value="Struct" />
-        <option name="com.jetbrains.cidr.lang.util.OCDeclarationKind" value="FunctionPredecl" />
-        <option name="com.jetbrains.cidr.lang.util.OCDeclarationKind" value="Function" />
-      </file>
-      <class>
-        <option name="com.jetbrains.cidr.lang.util.OCDeclarationKind" value="Property" />
-        <option name="com.jetbrains.cidr.lang.util.OCDeclarationKind" value="Synthesize" />
-        <option name="com.jetbrains.cidr.lang.util.OCDeclarationKind" value="InitMethod" />
-        <option name="com.jetbrains.cidr.lang.util.OCDeclarationKind" value="StaticMethod" />
-        <option name="com.jetbrains.cidr.lang.util.OCDeclarationKind" value="InstanceMethod" />
-        <option name="com.jetbrains.cidr.lang.util.OCDeclarationKind" value="DeallocMethod" />
-      </class>
-      <extensions>
-        <pair source="cpp" header="h" fileNamingConvention="NONE" />
-        <pair source="c" header="h" fileNamingConvention="NONE" />
-      </extensions>
-    </Objective-C-extensions>
-  </code_scheme>
-</component>

+ 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} .)
+include_directories(${X11_INCLUDE_DIR} ${XRANDR_INCLUDE_DIR} ${IRRLICHT_INCLUDE_DIR} ${LZ4_INCLUDE_DIR} ${SDL_INCLUDE_DIRS} ${SDL_MIXER_INCLUDE_DIRS} .)
 
 
 add_executable(
 add_executable(
         wallengine
         wallengine
@@ -60,4 +61,4 @@ add_executable(
         wallpaperengine/sound.h
         wallpaperengine/sound.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.
 
 

+ 78 - 16
main.cpp

@@ -8,12 +8,19 @@
 #include <SDL_mixer.h>
 #include <SDL_mixer.h>
 #include <SDL.h>
 #include <SDL.h>
 
 
+// support for randr extended screens
+#include <X11/Xlib.h>
+#include <X11/extensions/Xrandr.h>
+
 #include "wallpaperengine/shaders/compiler.h"
 #include "wallpaperengine/shaders/compiler.h"
 #include "wallpaperengine/project.h"
 #include "wallpaperengine/project.h"
 #include "wallpaperengine/irrlicht.h"
 #include "wallpaperengine/irrlicht.h"
 #include "wallpaperengine/irr/CImageLoaderTEX.h"
 #include "wallpaperengine/irr/CImageLoaderTEX.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;
@@ -25,7 +32,7 @@ int init_irrlicht()
     _irr_params.Bits = 16;
     _irr_params.Bits = 16;
     // _irr_params.DeviceType = irr::EIDT_X11;
     // _irr_params.DeviceType = irr::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;
@@ -36,7 +43,55 @@ int init_irrlicht()
     _irr_params.WithAlphaChannel = false;
     _irr_params.WithAlphaChannel = false;
     _irr_params.ZBufferBits = 24;
     _irr_params.ZBufferBits = 24;
     _irr_params.LoggingLevel = irr::ELL_DEBUG;
     _irr_params.LoggingLevel = irr::ELL_DEBUG;
-    _irr_params.WindowId = reinterpret_cast<void*> (WinID);
+
+    if (IsRootWindow == true)
+    {
+        Display* display = XOpenDisplay (NULL);
+        XRRScreenResources* screenResources = XRRGetScreenResources (display, DefaultRootWindow (display));
+
+        // there are some situations where xrandr returns null (like screen not using the extension)
+        if (screenResources != nullptr)
+        {
+            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));
+    }
 
 
     wp::irrlicht::device = irr::createDeviceEx (_irr_params);
     wp::irrlicht::device = irr::createDeviceEx (_irr_params);
 
 
@@ -84,7 +139,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;
 }
 }
 
 
 int main (int argc, char* argv[])
 int main (int argc, char* argv[])
@@ -96,26 +151,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':
@@ -141,8 +196,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;
@@ -224,7 +277,16 @@ int main (int argc, char* argv[])
 
 
             if (currentTime - lastTime > minimumTime)
             if (currentTime - lastTime > minimumTime)
             {
             {
-                wp::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
+                    wp::irrlicht::driver->setViewPort (*cur);
+                    wp::video::renderer::render ();
+                }
+
                 lastTime = currentTime;
                 lastTime = currentTime;
             }
             }
             else
             else

+ 1 - 1
wallpaperengine/video/renderer.cpp

@@ -43,7 +43,7 @@ namespace wp
         {
         {
             if (wp::irrlicht::driver == nullptr) return;
             if (wp::irrlicht::driver == nullptr) return;
 
 
-            wp::irrlicht::driver->beginScene(true, true, irr::video::SColor(0, 0, 0, 0));
+            wp::irrlicht::driver->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 ();