diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 6a81a7e..689157a 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -17,7 +17,7 @@ jobs: - name: Install cmake uses: lukka/get-cmake@v3.26.0 - name: Install dependencies - run: sudo apt install libsdl2-dev + run: sudo apt update && sudo apt install libsdl2-dev libconfig-dev libgtk-3-dev - name: Build run: mkdir -p build && cd build && cmake ../ && cmake --build . && cpack @@ -28,45 +28,25 @@ jobs: steps: - name: Checkout uses: actions/checkout@v3 - - name: Install cmake - uses: lukka/get-cmake@v3.26.0 - - name: Install MinGW - uses: egor-tensin/setup-mingw@v2 - - name: Install MSVC - uses: ilammy/msvc-dev-cmd@v1 - - name: Install wget - run: choco install wget - - name: Install dependencies` - run: | - wget -nv https://github.com/libsdl-org/SDL/releases/download/release-2.26.3/SDL2-devel-2.26.3-mingw.zip - 7z x -bd SDL2-devel-2.26.3-mingw.zip -omingw - wget -nv https://github.com/libsdl-org/SDL/releases/download/release-2.26.3/SDL2-devel-2.26.3-VC.zip - 7z x -bd SDL2-devel-2.26.3-VC.zip -omsvc - - name: Build with MSVC + - name: Install MSYS2 + uses: msys2/setup-msys2@v2 + with: + update: true + msystem: MINGW64 + install: >- + git + curl + unzip + mingw-w64-x86_64-cmake + mingw-w64-x86_64-gcc + mingw-w64-x86_64-gtk3 + mingw-w64-x86_64-SDL2 + mingw-w64-x86_64-libconfig + - name: Download SDL2 runtime + shell: msys2 {0} run: | - mkdir buildMSVC - cd buildMSVC - cmake -G "Visual Studio 17" -DSDL2_DIR=${{ github.workspace }}\msvc\SDL2-2.26.3\cmake -DSDL2_RUNTIME_DIR=${{ github.workspace }}\msvc\SDL2-2.26.3\lib\x64 ..\ - cmake --build . - cd .. - - name: Build with MinGW - run: | - mkdir buildMinGW - cd buildMinGW - cmake -G "MinGW Makefiles" -DSDL2_DIR=${{ github.workspace }}\mingw\SDL2-2.26.3\cmake -DSDL2_RUNTIME_DIR=${{ github.workspace }}\mingw\SDL2-2.26.3\x86_64-mingw32\bin -DCMAKE_BUILD_TYPE=Release ..\ - cmake --build . - - - macOS: - name: Build on MacOS - runs-on: macos-12 - - steps: - - name: Checkout - uses: actions/checkout@v3 - - name: Install cmake - uses: lukka/get-cmake@v3.26.0 - - name: Install dependencies` - run: brew install sdl2 + curl -L https://github.com/libsdl-org/SDL/releases/download/release-2.30.1/SDL2-2.30.1-win32-x64.zip > sdl2.zip + unzip sdl2.zip - name: Build - run: mkdir build && cd build && cmake ../ && cmake --build . && sudo cpack + shell: msys2 {0} + run: mkdir -p build && cd build && cmake -DSDL2_RUNTIME_DIR=${GITHUB_WORKSPACE} ../ && cmake --build . && ../distributeDLLs.sh && cpack diff --git a/.gitignore b/.gitignore index 8ec5a32..90b3ebb 100644 --- a/.gitignore +++ b/.gitignore @@ -1,10 +1,15 @@ resource.rc .DS_Store +compile_commands.json +.cache + data/ build/ *.res +.vscode + # Prerequisites *.d diff --git a/CMakeLists.txt b/CMakeLists.txt index 2b839e4..78672fa 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,19 +1,17 @@ cmake_minimum_required(VERSION 3.13) +set(CMAKE_EXPORT_COMPILE_COMMANDS ON) + project(lwp LANGUAGES C) -if(SDL2_RUNTIME_DIR) - string(REPLACE "\\" "/" SDL2_RUNTIME_DIR ${SDL2_RUNTIME_DIR}) -endif() - # Detect the platform -if (APPLE) - set(_UNAME "DARWIN") -elseif (WIN32) - set(_UNAME "WIN32") +if (MSYS OR MINGW) + set(_UNAME "WIN32") +elseif(UNIX) + set(_UNAME "LINUX") else() - set(_UNAME "LINUX") + message(FATAL_ERROR "Unsupported platform") endif() # Detect version @@ -35,123 +33,42 @@ if(NOT DEFINED PROGRAM_VERSION) message(WARNING "Can't determine Layered WallPaper version") endif() -set(_SOURCE_FILES - main.c - debug.c - parser.c - wallpaper.c - window.c - ) - -# Windows resource file -if(_UNAME STREQUAL "WIN32") - if(MINGW) - set(CMAKE_RC_COMPILER_INIT windres) - ENABLE_LANGUAGE(RC) - SET(CMAKE_RC_COMPILE_OBJECT - " -O coff -i -o ") - endif(MINGW) - - configure_file(${CMAKE_CURRENT_SOURCE_DIR}/resource.template.rc ${CMAKE_CURRENT_SOURCE_DIR}/resource.rc - @ONLY) - list(APPEND _SOURCE_FILES "resource.rc") -endif() - -# SDL2 dependency -find_package(SDL2 REQUIRED CONFIG) -set(_INCLUDE_DIRS ${SDL2_INCLUDE_DIRS}) -set(_LIBS ${SDL2_LIBRARIES}) - -if (_UNAME STREQUAL "DARWIN") - # MacOSX framework dependencies - list(APPEND _LIBS "-framework CoreGraphics" "-framework Foundation") -endif() - -if (_UNAME STREQUAL "LINUX") - # X11 dependency - find_package(X11 REQUIRED) - list(APPEND _INCLUDE_DIRS ${X11_INCLUDE_DIR}) - list(APPEND _LIBS ${X11_LIBRARIES}) -endif() - -option(LWP_INSTALL_LAUNCHD "Launch lwp on login (MacOSX only)" OFF) - # Config file set(_DEFAULT_CONFIG_FILE default.cfg) if(_UNAME STREQUAL "WIN32") set(_DEFAULT_CONFIG_FILE defaultWin.cfg) endif() -if (_UNAME STREQUAL "DARWIN") - set(_DEFAULT_CONFIG_FILE defaultMac.cfg) -endif() - -# Main executable -if (_UNAME STREQUAL "DARWIN") - add_executable(lwp MACOSX_BUNDLE ${_SOURCE_FILES}) -else() - add_executable(lwp ${_SOURCE_FILES}) -endif() - -# Windows specific properties for executable -if(_UNAME STREQUAL "WIN32") - set_property(TARGET lwp PROPERTY VS_DPI_AWARE "PerMonitor") -endif() -if(MSVC) - set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} /SUBSYSTEM:WINDOWS") -endif() +add_subdirectory(src/wlp) +link_directories(src/wlp) -target_compile_definitions(lwp PUBLIC __${_UNAME}) -target_include_directories(lwp PUBLIC ${_INCLUDE_DIRS}) -target_link_libraries(lwp PRIVATE ${_LIBS}) +add_subdirectory(src/core) +link_directories(src/core) # Installation rules if(_UNAME STREQUAL "WIN32") - install(TARGETS lwp - DESTINATION .) install(DIRECTORY wallpapers DESTINATION .) - install(FILES LICENSE.txt + install(DIRECTORY build/dlls/ DESTINATION .) - install(FILES ${_DEFAULT_CONFIG_FILE} + install(DIRECTORY src/window_templates + DESTINATION .) + install(FILES LICENSE.txt DESTINATION .) install(FILES ${SDL2_RUNTIME_DIR}/SDL2.dll DESTINATION .) install(FILES ${SDL2_RUNTIME_DIR}/README-SDL.txt DESTINATION .) -elseif(_UNAME STREQUAL "LINUX") - install(TARGETS lwp - DESTINATION usr/local/bin) +else() install(DIRECTORY wallpapers - DESTINATION usr/local/share/lwp) + DESTINATION share/lwp) + install(DIRECTORY src/window_templates + DESTINATION share/lwp) install(FILES LICENSE.txt - DESTINATION usr/local/share/lwp) - install(FILES ${_DEFAULT_CONFIG_FILE} - TYPE SYSCONF - RENAME lwp.cfg) -else() - install(TARGETS lwp - DESTINATION Layered_WallPaper) - install(DIRECTORY wallpapers - DESTINATION Layered_WallPaper) - install(FILES LICENSE.txt - DESTINATION Layered_WallPaper) - install(FILES ${_DEFAULT_CONFIG_FILE} - DESTINATION Layered_WallPaper - RENAME lwp.cfg) - install(FILES lwp.template.plist - DESTINATION Layered_WallPaper) - install (FILES setupPlist.command - DESTINATION Layered_WallPaper - RENAME Toggle_Autorun.command - PERMISSIONS OWNER_READ OWNER_WRITE OWNER_EXECUTE GROUP_READ GROUP_EXECUTE WORLD_READ WORLD_EXECUTE) - install (FILES setupPlist.command - DESTINATION . - RENAME Toggle_Autorun.command - PERMISSIONS OWNER_READ OWNER_WRITE OWNER_EXECUTE GROUP_READ GROUP_EXECUTE WORLD_READ WORLD_EXECUTE) - + DESTINATION share/lwp) endif() + # Installer if (_UNAME STREQUAL "WIN32") set(CPACK_GENERATOR NSIS) @@ -159,11 +76,8 @@ if (_UNAME STREQUAL "WIN32") elseif(_UNAME STREQUAL "LINUX") set(CPACK_GENERATOR TGZ) set(CPACK_INCLUDE_TOPLEVEL_DIRECTORY OFF) -elseif(_UNAME STREQUAL "DARWIN") - set(CPACK_GENERATOR DragNDrop) - set(CPACK_DMG_BACKGROUND_IMAGE ${CMAKE_CURRENT_SOURCE_DIR}/dmgBg.png) - set(CPACK_DMG_DS_STORE_SETUP_SCRIPT ${CMAKE_CURRENT_SOURCE_DIR}/setupDmg.applescript) endif() + set(CPACK_NSIS_MUI_ICON ${CMAKE_CURRENT_SOURCE_DIR}/icon.ico) set(CPACK_NSIS_MUI_UNIICON ${CMAKE_CURRENT_SOURCE_DIR}/icon.ico) set(CPACK_NSIS_INSTALLED_ICON_NAME ${CMAKE_CURRENT_SOURCE_DIR}/icon.ico) diff --git a/README.md b/README.md index 1202b64..cc31888 100644 --- a/README.md +++ b/README.md @@ -1,14 +1,15 @@ +
-# LWP +# Layered WallPaper -LWP allows You to create multi-layered parallax wallpapers.
+Layered WallPaper allows You to create multi-layered parallax wallpapers.
Each layer moves with Your mouse cursor, creating this beautiful effect. [![](https://img.shields.io/github/v/release/jszczerbinsky/lwp?style=for-the-badge)](https://github.com/jszczerbinsky/lwp/releases/latest) [![](https://img.shields.io/github/downloads/jszczerbinsky/lwp/total?style=for-the-badge)](https://github.com/jszczerbinsky/lwp/releases/latest) [![](https://img.shields.io/github/actions/workflow/status/jszczerbinsky/lwp/build.yml?style=for-the-badge)](https://github.com/jszczerbinsky/lwp) -[![](https://img.shields.io/discord/1077955077974794322?label=DISCORD&style=for-the-badge)](https://discord.gg/gHpbkXJD) +[![](https://img.shields.io/discord/1077955077974794322?label=DISCORD&style=for-the-badge)](https://discord.gg/JmkCqjYFQa) [Installation](#installation) • [Configuration](#configuration) • @@ -24,23 +25,25 @@ https://user-images.githubusercontent.com/38699473/220888934-09788a6b-873c-469b-
Linux - - #### Installation steps - + + ### Dependencies - Install `SDL2` using Your package manager - If You are using `Wayland`, You also must install `XWayland` + + #### Installation steps - Download `.tar.gz` package from [releases](https://github.com/jszczerbinsky/lwp/releases/latest) - - Extract the content to `/`: + - Extract the content to `/usr/local`: ```shell - sudo tar -o -xvf [archive name].tar.gz --directory / + sudo tar -o -xvf [archive name].tar.gz --directory /usr/local ``` - - Test lwp by running `lwp` - - Setting `reload_rootwindow=1` in config file may be necessary on some distributions for Layered WallPaper to work properly (see [configuration](#configuration)) - - To make lwp run on startup, add `lwp &` command to Your desktop enviroment `.rc` file + - Note that if You install lwp somewhere else than `/usr/local`, You need to set `LWP_PREFIX` env before running `lwp`. + - Test Layered WallPaper by running `lwp` + - Run `lwp`, then run it again to open the configuration window. Select wallpaper for each monitor. + - If You can't see any wallpaper try setting `Draw on root window` in application settings. This may be necessary on some distributions for Layered WallPaper to work properly (see [configuration](#configuration)) + - To make Layered WallPaper run on startup, add `lwp &` command to Your desktop enviroment `.rc` file #### Build from source instead - - Install `SDL2` using Your package manager. On some distributions `SDL2` doesn't contain development files, so it may be also necessary to install development version of `SDL2` - - If You are using `Wayland`, You also must install `XWayland` + - In some distributions `SDL2` doesn't contain development files, so it may be also necessary to install development version of `SDL2` - Install `CMake` - Clone the repository and prepare a `build` directory: @@ -56,151 +59,70 @@ https://user-images.githubusercontent.com/38699473/220888934-09788a6b-873c-469b- cmake --build . cpack ``` - - Extract `.tar.gz` package - ```shell - sudo tar -o -xvf [archive name].tar.gz --directory / - ``` - - Test lwp by running `lwp` - - Setting `reload_rootwindow=1` in config file may be necessary on some distributions for Layered WallPaper to work properly (see [configuration](#configuration)) - - To make lwp run on startup, add `lwp &` command to Your desktop enviroment `.rc` file + - After this `.tar.gz` package should appear. Follow the installation steps
-
- macOS - - #### Installation steps - - Download and run the installer from [releases](https://github.com/jszczerbinsky/lwp/releases/latest) - - Drag and drop Layered_WallPaper into Applications - - To make Layered WallPaper run on startup, run Toggle_Autorun.command - - To stop running Layered WallPaper on startup, run it again - - #### Build from source instead - - Install `SDL2` (homebrew: `brew install sdl2`) - - To build this project, You need to install `cmake` (homebrew: `brew install cmake`) - - Clone the repository: - ```zsh - git clone https://github.com/jszczerbinsky/lwp - cd lwp - - ``` - - Compile and generate installer - ```zsh - mkdir build - cd build - cmake ../ - cmake --build . - cpack -G DragNDrop - ``` - - DMG installer should appear, open it and drag Layered_WallPaper into Applications - - To make Layered WallPaper run on startup, run Toggle_Autorun.command - - To stop running Layered WallPaper on startup, run it again - -
-
Windows #### Installation steps - Download and run the installer from [releases](https://github.com/jszczerbinsky/lwp/releases/latest) - Layered WallPaper should run immediately after the installation + - Click the tray icon on the right side of Your taskbar to show the configuration window. Set the wallpapers for each monitor #### Build from source instead - - Layered WallPaper is built using [cmake](https://cmake.org/), so You must install it. - - This project supports `MinGW` and `MSVC` compilers. Using different one could lead to unpredicted behavior. If You want to use `MSVC`, it should be installed with Visual Studio. - - Download `SDL2` and `SDL2-devel` package for Your compiler from [SDL2 releases](https://github.com/libsdl-org/SDL/releases/latest) and extract them somewhere. - - You also must install [NSIS](https://nsis.sourceforge.io/Download). It's required to build the installer, which is needed to correctly set the registry keys, that will make Layered WallPaper run on OS startup etc. - - Clone the repository and create `build` directory - ```shell - git clone https://github.com/jszczerbinsky/lwp - cd lwp - mkdir -p build - cd build - ``` - - Type the following commands, replace square brackets elements with paths to extracted `SDL2` packages, that You've downloaded: + To compile Layered WallPaper on Windows you need to install [MSYS2](https://www.msys2.org/). After the installation follow the guide for setting up [GTK development enviroment](https://www.gtk.org/docs/installations/windows#using-gtk-from-msys2-packages). From now on continue using MSYS2 MinGW terminal (make sure you're using `MSYS2 MINGW64`/`MSYS2 MINGW32` instead of `MSYS2`). +##### Install the remaining dependencies +```shell +# For 64bit: +pacman -S mingw-w64-x86_64-cmake mingw-w64-x86_64-SDL2 mingw-w64-x86_64-gcc mingw-w64-x86_64-gtk3 mingw-w64-x86_64-libconfig - For `MSVC`: - ```shell - cmake -G "Visual Studio 17" -DSDL2_DIR=[PATH TO SDL2-MSVC-DEVEL DIRECTORY]\cmake -DSDL2_RUNTIME_DIR=[PATH TO SDL2 RUNTIME DIRECTORY] ../ - cmake --build . --config Release - cpack - ``` - For `MinGW`: - ```shell - cmake -G "MinGW Makefiles" -DSDL2_DIR=[PATH TO SDL2-MINGW-DEVEL DIRECTORY]\cmake -DSDL2_RUNTIME_DIR=[PATH TO SDL2 RUNTIME DIRECTORY] -DCMAKE_BUILD_TYPE=Release ../ - cmake --build . - cpack - ``` - - The installer should appear in `build` directory, that You've created earlier. After completing the installation Layered WallPaper should run immediately. - -
- -## Configuration +# For 32bit: +pacman -S mingw-w64-i686-cmake mingw-w64-x86_i686-SDL2 mingw-w64-x86_i686-gcc mingw-w64-x86_i686-gtk3 mingw-w64-x86_i686-libconfig +``` -#### Create a configuration file -
- Linux - - - Copy default config file to `.config/lwp/lwp.cfg`: - ```shell - mkdir ~/.config/lwp - cp /etc/lwp.cfg ~/.config/lwp/lwp.cfg - ``` - -
-
- macOS +##### Clone the repository +```shell +git clone https://github.com/jszczerbinsky/lwp +cd lwp +mkdir build +cd build +``` - - Copy default config file to `~/.config/lwp/lwp.cfg`: - ```zsh - mkdir -p ~/.config/lwp - cp /opt/lwp/lwp.cfg ~/.config/lwp/ - ``` -
-
- Windows - - - Press ⊞ Win + R - - Type `%appdata%` and press `Ok` - - Create new directory and name it `lwp` - - Copy file `C:\Program Files\lwp\defaultWin.cfg` to directory created in the previous step and rename it to `lwp.cfg` - - Open `lwp.cfg` in notepad +##### Compile and install +- Download [SDL2](https://github.com/libsdl-org/SDL/releases/latest) runtime package and unpack it. +- Compile the program +```shell +# Remember to use unix path format (instead of C:/path/to/dir use /c/path/to/dir) +cmake -DSDL2_RUNTIME_DIR=/path/to/dir ../ +cmake --build . +# Prepare the DLLs, that will be shipped with the program. +# The script is going to ask you which version of gdbus.exe should it use (32bit or 64bit) +../distributeDLLs.sh +cpack +``` +After this the installer should appear in the current directory.
-#### Using config file - -- Do not put spaces between `=` and values -- Do not leave trailing spaces -- Comments start with `#` -- Do not put strings in quotation marks +## Configuration -#### Available options: +### Open configuration window +- On Linux when `lwp` is already running in the background, run `lwp` again to show the window. +- On Windows You can click the icon on the right side of the task bar. -| Type | Name | Description | -| ------ | ------------ | ----------- | -| int | reload_rootwindow | Set this to 1 if You are using a compositor (linux only) | -| float | smooth | Smooth movement multipler | -| int | monitors | Monitors count | -| int | monitor[n]_x | Position of nth monitor in X axis | -| int | monitor[n]_y | Position of nth monitor in Y axis | -| int | monitor[n]_w | Width of nth monitor | -| int | monitor[n]_h | Height of nth monitor | -| string | monitor[n]_wallpaper | Absolute path to the wallpaper directory | -| int | monitor[n]_wallpaper_x | Position of the wallpaper relative to the monitor | -| int | monitor[n]_wallpaper_y | Position of the wallpaper relative to the monitor | -| int | monitor[n]_wallpaper_w | Wallpaper resolution | -| int | monitor[n]_wallpaper_h | Wallpaper resolution | -| int | target_fps | How many times per second should the wallpaper render (imprecise, hence "target") | +### Installing wallpapers +- To install wallpaper, copy the directory to `%LOCALAPPDATA%\lwp\wallpapers\` ## Creating Wallpapers -Want to share Your wallpaper? Join our [discord](https://discord.gg/gHpbkXJD)! +Want to share Your wallpaper? Join our [discord](https://discord.gg/JmkCqjYFQa)! Parallax wallpapers are not popular. Because of this if You want some cool parallax wallpaper, You have to either find a parallax game background on the internet and use it as a wallpaper or cut some real wallpaper into layers using Gimp or Photoshop. -#### How to create a wallpaper for lwp +#### How to create a wallpaper for Layered WallPaper - Create a directory for Your wallpaper - Save each layer to this directory as `.bmp` file and name them `1.bmp`, `2.bmp` ... (`1.bmp` is bottom most layer) - Create a wallpaper config file and name it `wallpaper.cfg` (You can make a copy from `C:\Program Files\lwp\wallpapers\default-fullhd\wallpaper.cfg`) @@ -224,8 +146,6 @@ C: | int | count | Wallpaper layers count | | float | movement_x | Mouse sensitivity in X axis | | float | movement_y | Mouse sensitivity in Y axis | -| float | movement[n]_x | Mouse sensitivity in X axis for nth layer (optional)| -| float | movement[n]_y | Mouse sensitivity in Y axis for nth layer (optional)| | int | repeat_x | Repeat the wallpaper in X axis | | int | repeat_y | Repeat the wallpaper in Y axis | diff --git a/debug.c b/debug.c deleted file mode 100644 index 2381d3d..0000000 --- a/debug.c +++ /dev/null @@ -1,37 +0,0 @@ -#include "debug.h" - -#include -#include - -void lwpLog(int type, const char *str, ...) -{ - char *typePrefixCodes; - char *typePrefix; - - switch (type) - { - case LOG_ERROR: - typePrefixCodes = "\x1b[31m\x1b[1m"; - typePrefix = "ERROR"; - break; - case LOG_INFO: - typePrefixCodes = "\x1b[34m\x1b[1m"; - typePrefix = "INFO"; - break; - case LOG_WARNING: - typePrefixCodes = "\x1b[33m\x1b[1m"; - typePrefix = "WARNING"; - break; - } - - printf("%s%s: \x1b[0m", typePrefixCodes, typePrefix); - - va_list args; - va_start(args, str); - vprintf(str, args); - va_end(args); - - putchar('\n'); - fflush(stdout); -} - diff --git a/debug.h b/debug.h deleted file mode 100644 index fde6f2a..0000000 --- a/debug.h +++ /dev/null @@ -1,10 +0,0 @@ -#ifndef DEBUG_H -#define DEBUG_H - -#define LOG_ERROR 0 -#define LOG_INFO 1 -#define LOG_WARNING 2 - -void lwpLog(int type, const char *str, ...); - -#endif diff --git a/default.cfg b/default.cfg deleted file mode 100644 index 1a03de4..0000000 --- a/default.cfg +++ /dev/null @@ -1,39 +0,0 @@ -# ██╗ ██╗ ██╗██████╗ -# ██║ ██║ ██║██╔══██╗ -# ██║ ██║ █╗ ██║██████╔╝ -# ██║ ██║███╗██║██╔═══╝ -# ███████╗╚███╔███╔╝██║ -# ╚══════╝ ╚══╝╚══╝ ╚═╝ - -# If You are using a compositor, or lwp window deosn't show, -# try setting this to 1 -reload_rootwindow=0 - -# Smooth movement -# Increasing this value will make the wallpaper layers move faster -smooth=8.0 - -# Monitors count -monitors=1 - -# Monitor position -monitor1_x=0 -monitor1_y=0 - -# Monitor resolution -monitor1_w=1920 -monitor1_h=1080 - -# Absolute path to the wallpaper directory -monitor1_wallpaper=/usr/local/share/lwp/wallpapers/default-fullhd - -# Wallpaper size and position relative to Your monitor -# Wallpaper resolution ratio should be the same as in original image -monitor1_wallpaper_x=0 -monitor1_wallpaper_y=0 -monitor1_wallpaper_w=1920 -monitor1_wallpaper_h=1080 - -# How many times per second should the wallpaper render -# (imprecise, but accurate enough) -target_fps=60 diff --git a/defaultMac.cfg b/defaultMac.cfg deleted file mode 100644 index 88372be..0000000 --- a/defaultMac.cfg +++ /dev/null @@ -1,36 +0,0 @@ -# ██╗ ██╗ ██╗██████╗ -# ██║ ██║ ██║██╔══██╗ -# ██║ ██║ █╗ ██║██████╔╝ -# ██║ ██║███╗██║██╔═══╝ -# ███████╗╚███╔███╔╝██║ -# ╚══════╝ ╚══╝╚══╝ ╚═╝ - -# Smooth movement -# Increasing this value will make the wallpaper layers move faster -smooth=8.0 - -# Monitors count -monitors=1 - -# Monitor position -monitor1_x=0 -monitor1_y=0 - -# Monitor resolution -monitor1_w=1920 -monitor1_h=1080 - -# Absolute path to the wallpaper directory -# Leave the value as empty to use the default wallpaper -monitor1_wallpaper=/Applications/Layered_WallPaper/wallpapers/default-fullhd - -# Wallpaper size and position relative to Your monitor -# Wallpaper resolution ratio should be the same as in original image -monitor1_wallpaper_x=0 -monitor1_wallpaper_y=0 -monitor1_wallpaper_w=1920 -monitor1_wallpaper_h=1080 - -# How many times per second should the wallpaper render -# (imprecise, but accurate enough) -target_fps=60 diff --git a/defaultWin.cfg b/defaultWin.cfg deleted file mode 100644 index 761e0fc..0000000 --- a/defaultWin.cfg +++ /dev/null @@ -1,36 +0,0 @@ -# ██╗ ██╗ ██╗██████╗ -# ██║ ██║ ██║██╔══██╗ -# ██║ ██║ █╗ ██║██████╔╝ -# ██║ ██║███╗██║██╔═══╝ -# ███████╗╚███╔███╔╝██║ -# ╚══════╝ ╚══╝╚══╝ ╚═╝ - -# Smooth movement -# Increasing this value will make the wallpaper layers move faster -smooth=8.0 - -# Monitors count -monitors=1 - -# Monitor position -monitor1_x=0 -monitor1_y=0 - -# Monitor resolution -monitor1_w=1920 -monitor1_h=1080 - -# Absolute path to the wallpaper directory -# Leave the value as empty to use the default wallpaper -monitor1_wallpaper= - -# Wallpaper size and position relative to Your monitor -# Wallpaper resolution ratio should be the same as in original image -monitor1_wallpaper_x=0 -monitor1_wallpaper_y=0 -monitor1_wallpaper_w=1920 -monitor1_wallpaper_h=1080 - -# How many times per second should the wallpaper render -# (imprecise, but accurate enough) -target_fps=60 diff --git a/distributeDLLs.sh b/distributeDLLs.sh new file mode 100644 index 0000000..6a8d53d --- /dev/null +++ b/distributeDLLs.sh @@ -0,0 +1,23 @@ +#!/bin/bash + +mkdir -p dlls +mkdir -p dlls/lib +mkdir -p dlls/lib/gdk-pixbuf-2.0 +mkdir -p dlls/lib/gdk-pixbuf-2.0/2.10.0 + +echo +PS3='Choose the correct version of gdbus: ' +options=("/mingw64/bin/gdbus.exe" "/mingw32/bin/gdbus.exe") +select opt in "${options[@]}" +do + echo "Preparing gdbus.exe..." + cp $opt ./dlls/ + break; +done + +echo "Preparing DLLs..." + +ldd ./src/core/lwp.exe | grep '\/mingw.*\.dll' -o | xargs -I{} cp "{}" ./dlls/ +cp /mingw64/lib/gdk-pixbuf-2.0/2.10.0/loaders.cache ./dlls/lib/gdk-pixbuf-2.0/2.10.0/loaders.cache + +echo "Done" \ No newline at end of file diff --git a/dmgBg.png b/dmgBg.png deleted file mode 100644 index 99bf592..0000000 Binary files a/dmgBg.png and /dev/null differ diff --git a/install.bat b/install.bat deleted file mode 100644 index cfea051..0000000 --- a/install.bat +++ /dev/null @@ -1,72 +0,0 @@ -@echo off -cd %SystemRoot%\system32 -title Install LWP - -call :logo -net session >nul 2>&1 -if not %ERRORLEVEL% equ 0 ( - echo Run me as admin - pause>nul - exit -) - -call :logo -echo. -echo If You enjoy lwp, You can give it a start on github -echo https://github.com/jszczerbinsky/lwp -echo. -echo Lwp will be installed on Your computer -echo Click any key to display the license -pause > nul - -cls -echo ________________________________________________________________________________________________________________________ -type "%~dp0\data\LICENSE.txt" -echo ________________________________________________________________________________________________________________________ -echo. -echo By continuing the installation You accept the license conditions -echo. -set /p val="Continue? (y/n) > " -if not %val%==y ( - call :logo - echo You have to accept the license to continue installation - echo Installator will exit now - echo. - echo Press any key to continue... - pause>nul - exit -) -call :logo -echo Starting installation -echo. -path=%ProgramFiles% -echo Copying files... -robocopy "%~dp0\data" "%path%\lwp" /E /NFL /NDL /NJH /NJS /nc /ns /np -echo Adding lwp to autorun... -reg add "HKEY_LOCAL_MACHINE\Software\Microsoft\Windows\CurrentVersion\Run" /v "lwp" /t REG_EXPAND_SZ /d "%path%\lwp\lwp.exe" /f > nul -echo Creating uninstaller... -reg add "HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\layeredWallPaper" /f > nul -reg add "HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\layeredWallPaper" /v "UninstallString" /t REG_SZ /d "cmd /c \"%path%\lwp\uninstall.bat\"" /f > nul -reg add "HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\layeredWallPaper" /v "DisplayName" /t REG_SZ /d "Layered WallPaper" /f > nul -reg add "HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\layeredWallPaper" /v "DisplayIcon" /t REG_SZ /d "%path%\lwp\lwp.exe" /f > nul -reg add "HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\layeredWallPaper" /v "Publisher" /t REG_SZ /d "Jakub Szczerbinski" /f > nul -reg add "HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\layeredWallPaper" /v "URLInfoAbout" /t REG_SZ /d "https://github.com/jszczerbinsky/lwp" /f > nul - -echo. -echo Lwp has been successfuly installed on Your computer! -start "" "%path%\lwp\lwp.exe" -pause > nul -exit - -:logo -cls -echo. -echo. -echo " __ _ ______ " -echo " / /| | / / __ \ " -echo " / / | | /| / / /_/ / " -echo " / /__| |/ |/ / ____/ " -echo " /_____/__/|__/_/ " -echo. -echo. -exit /B 0 \ No newline at end of file diff --git a/lwp.template.plist b/lwp.template.plist deleted file mode 100644 index c10c25f..0000000 --- a/lwp.template.plist +++ /dev/null @@ -1,22 +0,0 @@ - - - - - Label - jszczerbinsky.lwp - - LaunchOnlyOnce - - - RunAtLoad - - - UserName - @user@ - - ProgramArguments - - @binpath@ - - - diff --git a/main.c b/main.c deleted file mode 100644 index def3652..0000000 --- a/main.c +++ /dev/null @@ -1,240 +0,0 @@ -#include "main.h" - -#include "debug.h" -#include "parser.h" -#include "platform_guard.h" -#include "wallpaper.h" -#include "window.h" - -static int lerp(int a, int b, float t) -{ - if (t > 1) t = 1; - return (int)((float)a + (float)t * ((float)b - (float)a)); -} - -static int init(App *app, Config *cfg) -{ - if (SDL_Init(SDL_INIT_VIDEO | SDL_INIT_EVENTS) != 0) - { - lwpLog(LOG_ERROR, "%s", SDL_GetError()); - return 0; - } - - initWindow(app, cfg); - - app->renderer = - SDL_CreateRenderer(app->window, -1, SDL_RENDERER_ACCELERATED | SDL_RENDERER_PRESENTVSYNC); - if (app->renderer == NULL) - { - lwpLog(LOG_ERROR, "%s", SDL_GetError()); - return 0; - } - - return 1; -} - -#ifdef __WIN32 -static void initCmd() -{ - // Create console - AllocConsole(); - AttachConsole(ATTACH_PARENT_PROCESS); - freopen("CONOUT$", "w", stdout); - HANDLE hOut = GetStdHandle(STD_OUTPUT_HANDLE); - DWORD dwMode = 0; - GetConsoleMode(hOut, &dwMode); - SetConsoleMode(hOut, dwMode | 0x0004); - - // Remove closing button (because closing it closes the entire app) - HWND hwnd = GetConsoleWindow(); - HMENU hMenu = GetSystemMenu(hwnd, FALSE); - DeleteMenu(hMenu, SC_CLOSE, MF_BYCOMMAND); - - // Set console title - SetConsoleTitle("Layered WallPaper"); -} -BOOL monitorenumproc( - HMONITOR monitor, - HDC hdc, - LPRECT rect, - LPARAM param -) -{ - - int px = GetSystemMetrics(SM_XVIRTUALSCREEN); - int py = GetSystemMetrics(SM_YVIRTUALSCREEN); - - MONITORINFO monitorInfo; - monitorInfo.cbSize = sizeof(MONITORINFO); - - GetMonitorInfo(monitor, &monitorInfo); - lwpLog(LOG_INFO, " Monitor: position %ldx%ld, size %ldx%ld %s", - monitorInfo.rcMonitor.left - px, - monitorInfo.rcMonitor.top - py, - monitorInfo.rcMonitor.right - monitorInfo.rcMonitor.left, - monitorInfo.rcMonitor.bottom - monitorInfo.rcMonitor.top, - (monitorInfo.dwFlags & MONITORINFOF_PRIMARY) == MONITORINFOF_PRIMARY ? "primary" : "" - ); - - return TRUE; -} -static void scanMonitors() -{ - lwpLog(LOG_INFO, "Scanning monitors..."); - EnumDisplayMonitors(NULL, NULL, &monitorenumproc, NULL); -} -#endif - -int main(int argc, char *argv[]) -{ - lwpLog(LOG_INFO, "Starting Layered WallPaper"); - -#ifdef __WIN32 - if (argc == 2 && strcmp(argv[1], "/console") == 0) initCmd(); - initTrayIcon(); - - scanMonitors(); -#endif - - App app; - Config cfg; - - int canRender = 1; - - if (!parseConfig(&app, &cfg) || !init(&app, &cfg) || !loadMonitors(&app, &cfg)) canRender = 0; - - SDL_Event event; - int quit = 0; - - int mx = 0; - int my = 0; - - while (!quit) - { - if(canRender) - { - static int currentX = 0; - static int currentY = 0; - - static int lastTicks = 0; - - int ticks = SDL_GetTicks(); - float dT = (ticks - lastTicks) / 1000.0f; - lastTicks = ticks; - - #ifdef __WIN32 - POINT mPos; - GetCursorPos(&mPos); - mx = mPos.x - GetSystemMetrics(SM_XVIRTUALSCREEN); - my = mPos.y - GetSystemMetrics(SM_YVIRTUALSCREEN); - #else - SDL_GetGlobalMouseState(&mx, &my); - #endif - - while (SDL_PollEvent(&event)) - if (event.type == SDL_QUIT) quit = 1; - - currentX = lerp(currentX, mx, dT * cfg.smooth); - currentY = lerp(currentY, my, dT * cfg.smooth); - - for (int m = 0; m < cfg.monitorsCount; m++) - { - int relativeCurrentX = currentX - cfg.monitors[m].x; - int relativeCurrentY = currentY - cfg.monitors[m].y; - - if (relativeCurrentX < 0) relativeCurrentX = 0; - if (relativeCurrentY < 0) relativeCurrentY = 0; - if (relativeCurrentX > cfg.monitors[m].w) relativeCurrentX = cfg.monitors[m].w; - if (relativeCurrentY > cfg.monitors[m].h) relativeCurrentY = cfg.monitors[m].h; - - SDL_SetRenderTarget(app.renderer, cfg.monitors[m].wallpaper.tex); - SDL_RenderClear(app.renderer); - - for (int i = 0; i < cfg.monitors[m].wallpaper.layersCount; i++) - { - SDL_Rect src = { - .x = 0, - .y = 0, - .w = cfg.monitors[m].wallpaper.originalW, - .h = cfg.monitors[m].wallpaper.originalH, - }; - - int x = -((relativeCurrentX - cfg.monitors[m].w / 2) * - cfg.monitors[m].wallpaper.layers[i].sensitivityX); - int y = -((relativeCurrentY - cfg.monitors[m].h / 2) * - cfg.monitors[m].wallpaper.layers[i].sensitivityY); - - for (int k = -cfg.monitors[m].wallpaper.repeatY; k <= cfg.monitors[m].wallpaper.repeatY; - k++) - { - for (int j = -cfg.monitors[m].wallpaper.repeatX; j <= cfg.monitors[m].wallpaper.repeatX; - j++) - { - SDL_Rect dest = { - .x = x + j * cfg.monitors[m].wallpaperW, - .y = y + k * cfg.monitors[m].wallpaperH, - .w = cfg.monitors[m].wallpaperW, - .h = cfg.monitors[m].wallpaperH, - }; - - SDL_RenderCopy(app.renderer, cfg.monitors[m].wallpaper.layers[i].tex, &src, &dest); - } - } - } - - SDL_SetRenderTarget(app.renderer, cfg.monitors[m].tex); - - SDL_Rect src = { - .x = 0, - .y = 0, - .w = cfg.monitors[m].wallpaperW, - .h = cfg.monitors[m].wallpaperH, - }; - - SDL_Rect dest = { - .x = cfg.monitors[m].wallpaperX, - .y = cfg.monitors[m].wallpaperY, - .w = cfg.monitors[m].wallpaperW, - .h = cfg.monitors[m].wallpaperH, - }; - - SDL_RenderCopy(app.renderer, cfg.monitors[m].wallpaper.tex, &src, &dest); - - SDL_SetRenderTarget(app.renderer, NULL); - - SDL_Rect finalSrc = { - .x = 0, - .y = 0, - .w = cfg.monitors[m].w, - .h = cfg.monitors[m].h, - }; - - SDL_Rect finalDest = { - .x = cfg.monitors[m].x, - .y = cfg.monitors[m].y, - .w = cfg.monitors[m].w, - .h = cfg.monitors[m].h, - }; - - SDL_RenderCopy(app.renderer, cfg.monitors[m].tex, &finalSrc, &finalDest); - } - SDL_RenderPresent(app.renderer); - } - SDL_Delay(1000 / cfg.targetFPS); -#ifdef __WIN32 - if(!updateTrayIcon()) quit = 1; -#endif - } - -#ifdef __WIN32 - removeTrayIcon(); -#endif - - freeConfig(&cfg); - - SDL_DestroyRenderer(app.renderer); - SDL_DestroyWindow(app.window); - SDL_Quit(); - - return 0; -} diff --git a/main.h b/main.h deleted file mode 100644 index 55d0e08..0000000 --- a/main.h +++ /dev/null @@ -1,68 +0,0 @@ -#ifndef MAIN_H -#define MAIN_H - -#ifdef _MSC_VER -#define PATH_MAX MAX_PATH -#include -#else -#include -#endif - -#ifdef __WIN32 -#include -#include -#elif __DARWIN -#include -#include -#include -#include -#include -#include -#elif __LINUX -#include -#include -#include -#include -#include -#endif - -typedef struct -{ - float sensitivityX; - float sensitivityY; - SDL_Texture *tex; -} Layer; - -typedef struct -{ - char dirPath[PATH_MAX]; - int repeatX, repeatY; - int layersCount; - Layer *layers; - int originalW, originalH; - SDL_Texture *tex; -} Wallpaper; - -typedef struct -{ - int x, y, w, h; - int wallpaperX, wallpaperY, wallpaperW, wallpaperH; - SDL_Texture *tex; - Wallpaper wallpaper; -} Monitor; -typedef struct -{ - int reloadRootWnd; - int monitorsCount; - float smooth; - int targetFPS; - Monitor *monitors; -} Config; - -typedef struct -{ - SDL_Window *window; - SDL_Renderer *renderer; -} App; - -#endif // MAIN_H diff --git a/parser.c b/parser.c deleted file mode 100644 index 85b0c76..0000000 --- a/parser.c +++ /dev/null @@ -1,302 +0,0 @@ -#include "parser.h" - -#include -#include - -#include "debug.h" -#include "wallpaper.h" - -#define TYPE_FLOAT 0 -#define TYPE_INT 1 -#define TYPE_STR 2 - -#ifdef __WIN32 -static void getline(char **buff, size_t *buffSize, FILE *f) -{ - long int startPos = ftell(f); - int length = 1; - char c; - do - { - c = fgetc(f); - length++; - } while (c != '\n' && !feof(f)); - - if (*buffSize < length) - { - *buff = realloc(*buff, length * sizeof(char)); - *buffSize = length * sizeof(char); - } - - fseek(f, startPos, SEEK_SET); - - fgets(*buff, length - 1, f); - (*buff)[length - 1] = '\0'; - fgetc(f); -} -#endif - -static FILE *openConfigFile() -{ - FILE *f; - char userConfigPath[PATH_MAX]; - -#ifdef __WIN32 - strcpy(userConfigPath, getenv("AppData")); - strcat(userConfigPath, "\\lwp\\lwp.cfg"); -#else - char *xdgConfigHome = getenv("XDG_CONFIG_HOME"); - if (xdgConfigHome) - { - strcpy(userConfigPath, xdgConfigHome); - strcat(userConfigPath, "/lwp/lwp.cfg"); - } - else - { - struct passwd *pw = getpwuid(getuid()); - strcpy(userConfigPath, pw->pw_dir); - strcat(userConfigPath, "/.config/lwp/lwp.cfg"); - } -#endif - - f = fopen(userConfigPath, "r"); - if (!f) - { - lwpLog(LOG_INFO, "User config file not found, opening default config instead"); - char defaultConfigPath[PATH_MAX]; -#ifdef __WIN32 - GetModuleFileNameA(NULL, defaultConfigPath, PATH_MAX); - char *ptr = defaultConfigPath + strlen(defaultConfigPath) - 1; - while (*ptr != '\\') ptr--; - *ptr = '\0'; - strcat(defaultConfigPath, "\\defaultWin.cfg"); - - f = fopen(defaultConfigPath, "r"); -#elif __DARWIN - strcpy(defaultConfigPath, "/Applications/Layered_WallPaper/lwp.cfg"); - - f = fopen(defaultConfigPath, "r"); -#else - char *sysConfDir = getenv("sysconfdir"); - if (sysConfDir) - { - strcpy(defaultConfigPath, sysConfDir); - strcat(defaultConfigPath, "/lwp.cfg"); - } - else - strcpy(defaultConfigPath, "/etc/lwp.cfg"); - - f = fopen(defaultConfigPath, "r"); -#endif - if (!f) lwpLog(LOG_ERROR, "Default config file not found!"); - } - - return f; -} - -static int findLine(FILE *f, const char *name, int type, void *output) -{ - char *buff = NULL; - size_t buffSize = 0; - - int found = 0; - - fseek(f, 0, SEEK_SET); - - do - { - getline(&buff, &buffSize, f); - - if (buffSize > 0 && buff[0] != '#') - { - if (strncmp(name, buff, strlen(name)) == 0) - { - char *valuePtr = buff; - while (*valuePtr != '=' && *valuePtr != '\0') - { - valuePtr++; - } - - if (*valuePtr == '=') - { - valuePtr++; - - if (valuePtr[strlen(valuePtr) - 1] == '\n') valuePtr[strlen(valuePtr) - 1] = '\0'; - - found = 1; - - switch (type) - { - case TYPE_INT: - *(int *)output = atoi(valuePtr); - break; - case TYPE_FLOAT: - *(float *)output = atof(valuePtr); - break; - case TYPE_STR: - strcpy((char *)output, valuePtr); - break; - } - } - } - } - } while (!found && buffSize > 0 && !feof(f)); - - free(buff); - return found; -} - -int parseConfig(App *app, Config *cfg) -{ - lwpLog(LOG_INFO, "Loading config file"); - - FILE *f = openConfigFile(); - - if (!findLine(f, "monitors", TYPE_INT, &cfg->monitorsCount)) - { - lwpLog(LOG_ERROR, "Can't find line 'monitors' in config"); - return 0; - } - lwpLog(LOG_INFO, " monitors: %d", cfg->monitorsCount); - - if (!findLine(f, "smooth", TYPE_FLOAT, &cfg->smooth)) - { - lwpLog(LOG_INFO, "Can't find line 'smooth' in config, setting to default value"); - cfg->smooth = 8; - } - lwpLog(LOG_INFO, " smooth: %f", cfg->smooth); - - if (!findLine(f, "target_fps", TYPE_INT, &cfg->targetFPS)) - { - lwpLog(LOG_INFO, "Can't find line 'target_fps' in config, setting to default value"); - cfg->targetFPS = 60; - } - lwpLog(LOG_INFO, " target_fps: %d", cfg->targetFPS); - -#ifdef __LINUX - if (!findLine(f, "reload_rootwindow", TYPE_INT, &cfg->reloadRootWnd)) - { - lwpLog(LOG_ERROR, "Can't find line 'reload_rootwindow' in config"); - return 0; - } - lwpLog(LOG_INFO, " reload_rootwindow: %d", cfg->reloadRootWnd); -#endif - - cfg->monitors = malloc(cfg->monitorsCount * sizeof(Monitor)); - - for (int m = 0; m < cfg->monitorsCount; m++) - { - char wallpaperPath[PATH_MAX]; - - const int PARAMS_COUNT = 9; - - const char *paramStr[] = {"wallpaper", "x", "y", "w", "h", - "wallpaper_x", "wallpaper_y", "wallpaper_w", "wallpaper_h"}; - void *outputs[] = { - wallpaperPath, - &cfg->monitors[m].x, - &cfg->monitors[m].y, - &cfg->monitors[m].w, - &cfg->monitors[m].h, - &cfg->monitors[m].wallpaperX, - &cfg->monitors[m].wallpaperY, - &cfg->monitors[m].wallpaperW, - &cfg->monitors[m].wallpaperH, - }; - - char str[100]; - - for (int p = 0; p < PARAMS_COUNT; p++) - { - snprintf(str, 100, "monitor%d_%s", m + 1, paramStr[p]); - if (!findLine(f, str, (p == 0 ? TYPE_STR : TYPE_INT), outputs[p])) - { - lwpLog(LOG_ERROR, "Can't find line '%s' in config", str); - return 0; - } - if(p > 0) - lwpLog(LOG_INFO, " %s: %d", str, *(int*)(outputs[p])); - } - -#ifdef __WIN32 - if (strlen(wallpaperPath) < 2) - { - GetModuleFileNameA(NULL, wallpaperPath, PATH_MAX); - char *ptr = wallpaperPath + strlen(wallpaperPath) - 1; - while (*ptr != '\\') ptr--; - *ptr = '\0'; - strcat(wallpaperPath, "\\wallpapers\\default-fullhd"); - } -#endif - - strncpy(cfg->monitors[m].wallpaper.dirPath, wallpaperPath, PATH_MAX); - lwpLog(LOG_INFO, " monitor%d_wallpaper: %s", m+1, wallpaperPath); - } - - fclose(f); - lwpLog(LOG_INFO, "Config file loaded"); - return 1; -} - -int parseWallpaperConfig(Wallpaper *wallpaper, const char *path) -{ - lwpLog(LOG_INFO, "Loading wallpaper config"); - FILE *f = fopen(path, "r"); - if (!f) - { - lwpLog(LOG_ERROR, "Wallpaper config file (%s) doesn't exist", path); - return 0; - } - - float defaultMovementX, defaultMovementY; - - const int PARAMS_COUNT = 5; - const char *paramStr[] = {"count", "movement_x", "movement_y", "repeat_x", "repeat_y"}; - const int types[] = {TYPE_INT, TYPE_FLOAT, TYPE_FLOAT, TYPE_INT, TYPE_INT}; - void *outputs[] = { - &wallpaper->layersCount, &defaultMovementX, &defaultMovementY, - &wallpaper->repeatX, &wallpaper->repeatY, - }; - - for (int p = 0; p < PARAMS_COUNT; p++) - { - if (!findLine(f, paramStr[p], types[p], outputs[p])) - { - lwpLog(LOG_ERROR, "Can't find line '%s' in config", paramStr[p]); - return 0; - } - - if (types[p] == TYPE_FLOAT) - lwpLog(LOG_INFO, " %s: %f", paramStr[p], *(float*)(outputs[p])); - else - lwpLog(LOG_INFO, " %s: %d", paramStr[p], *(int*)(outputs[p])); - } - wallpaper->layers = malloc(wallpaper->layersCount * sizeof(Layer)); - - lwpLog(LOG_INFO, " Each layer movements:"); - - char str[100]; - for (int l = 0; l < wallpaper->layersCount; l++) - { - snprintf(str, 100, "movement%d_x", l + 1); - if (!findLine(f, str, TYPE_FLOAT, &wallpaper->layers[l].sensitivityX)) - wallpaper->layers[l].sensitivityX = defaultMovementX * l; - lwpLog(LOG_INFO, " %s: %f", str, wallpaper->layers[l].sensitivityX); - - snprintf(str, 100, "movement%d_y", l + 1); - if (!findLine(f, str, TYPE_FLOAT, &wallpaper->layers[l].sensitivityY)) - wallpaper->layers[l].sensitivityY = defaultMovementY * l; - lwpLog(LOG_INFO, " %s: %f", str, wallpaper->layers[l].sensitivityY); - } - - fclose(f); - - lwpLog(LOG_INFO, "Wallpaper config file loaded"); - return 1; -} - -void freeConfig(Config *cfg) -{ - for (int i = 0; i < cfg->monitorsCount; i++) freeMonitor(&cfg->monitors[i]); - free(cfg->monitors); -} diff --git a/parser.h b/parser.h deleted file mode 100644 index 55fa65a..0000000 --- a/parser.h +++ /dev/null @@ -1,10 +0,0 @@ -#ifndef PARSER_H -#define PARSER_H - -#include "main.h" - -int parseConfig(App *app, Config *cfg); -int parseWallpaperConfig(Wallpaper *wallpaper, const char *path); -void freeConfig(Config *cfg); - -#endif diff --git a/setupDmg.applescript b/setupDmg.applescript deleted file mode 100755 index d3bdc84..0000000 --- a/setupDmg.applescript +++ /dev/null @@ -1,21 +0,0 @@ -on run argv - tell application "Finder" - tell disk (item 1 of argv) - open - set current view of container window to icon view - set toolbar visible of container window to false - set statusbar visible of container window to false - set the bounds of container window to {400, 100, 1000, 530} - set theViewOptions to the icon view options of container window - set arrangement of theViewOptions to not arranged - set icon size of theViewOptions to 72 - set background picture of theViewOptions to file ".background:background.png" - set position of item "Applications" of container window to {450,120} - set position of item "Layered_WallPaper" of container window to {130,120} - set position of item "Toggle_Autorun.command" of container window to {260,330} - update without registering applications - delay 5 - close - end tell - end tell -end run diff --git a/setupPlist.command b/setupPlist.command deleted file mode 100755 index 143007b..0000000 --- a/setupPlist.command +++ /dev/null @@ -1,16 +0,0 @@ -clear - -if [[ ! -a ~/Library/LaunchAgents/lwp.plist ]]; then - mkdir -p ~/Library/LaunchAgents - cp /Applications/Layered_WallPaper/lwp.template.plist ~/Library/LaunchAgents/lwp.plist - sed -i "" "s/@user@/$(whoami)/g" ~/Library/LaunchAgents/lwp.plist - sed -i "" "s^@binpath@^/Applications/Layered_WallPaper/lwp.app/Contents/MacOS/lwp^g" ~/Library/LaunchAgents/lwp.plist - launchctl load ~/Library/LaunchAgents/lwp.plist - - echo Layered WallPaper has been added to autostart -else - launchctl unload ~/Library/LaunchAgents/lwp.plist - rm ~/Library/LaunchAgents/lwp.plist - - echo Layered WallPaper has been removed from autostart -fi diff --git a/src/common.h b/src/common.h new file mode 100644 index 0000000..e17526b --- /dev/null +++ b/src/common.h @@ -0,0 +1,108 @@ +#ifndef COMMON_H +#define COMMON_H + +#ifdef __LINUX +#include +#else +#include +#endif + +#define MONITOR_NAME_MAX 100 +#define WALLPAPER_NAME_MAX 100 + +#define DEFAULT_LINUX_PREFIX "/usr/local" + +typedef struct +{ + int x; + int y; + int w; + int h; +} Bounds; + +typedef struct +{ + float sensitivityX; + float sensitivityY; +} LayerConfig; + +typedef struct +{ + int loaded; + int repeatX; + int repeatY; + int layersCount; + LayerConfig *layerConfigs; +} WallpaperConfig; + +typedef struct +{ + char name[WALLPAPER_NAME_MAX]; + char dirPath[PATH_MAX]; + int isDefault; + WallpaperConfig config; +} WallpaperInfo; + +typedef struct +{ + int loaded; + char wlpName[WALLPAPER_NAME_MAX]; + Bounds wlpBounds; +} MonitorConfig; + +typedef struct +{ + char name[MONITOR_NAME_MAX]; + Bounds bounds; + MonitorConfig config; +} MonitorInfo; + +typedef struct +{ + int drawOnRootWindow; + int targetFps; + char renderQuality[8]; +} AppConfig; + +// +// paths.c +// + +#define APP_DIR_BIN 0 +#define APP_DIR_SHARE 1 +#define APP_DIR_USER_SETTINGS 2 + +void getAppDir(char *buff, int type); + +void getMonitorCfgPath(char *buff, const char *name); +void getWlpCfgPath(char *buff, const char *dirPath); +void getAppCfgPath(char *buff); +void getLogPath(char *buff); + +void createUserDirs(); + +// +// monitorScanner.c +// + +MonitorInfo *scanMonitors(int *count); + +// +// wallpaperScanner.c +// + +WallpaperInfo *scanWallpapers(int *count); + +// +// config.c +// + +void saveMonitorConfig(const char *name, MonitorConfig *mc); +int loadMonitorConfig(const char *name, MonitorConfig *mc); + +int loadAppConfig(AppConfig *ac); +void saveAppConfig(AppConfig *ac); + +int loadWallpaperConfig(const char *dirName, WallpaperConfig *wc); + +#endif diff --git a/src/common/config.c b/src/common/config.c new file mode 100644 index 0000000..292c327 --- /dev/null +++ b/src/common/config.c @@ -0,0 +1,204 @@ +#include +#include +#include + +#include "../common.h" + +#define CONFIG_DEFAULT 0 +#define CONFIG_USER 1 + +static void generateEmptyMonitorConfig(MonitorConfig *mc) +{ + sprintf(mc->wlpName, ""); + mc->wlpBounds.x = 0; + mc->wlpBounds.y = 0; + mc->wlpBounds.w = 1920; + mc->wlpBounds.h = 1080; +} + +void saveMonitorConfig(const char *name, MonitorConfig *mc) +{ + config_t cfg; + config_setting_t *root, *setting; + + config_init(&cfg); + root = config_root_setting(&cfg); + + setting = config_setting_add(root, "wlpName", CONFIG_TYPE_STRING); + config_setting_set_string(setting, mc->wlpName); + + setting = config_setting_add(root, "x", CONFIG_TYPE_INT); + config_setting_set_int(setting, mc->wlpBounds.x); + setting = config_setting_add(root, "y", CONFIG_TYPE_INT); + config_setting_set_int(setting, mc->wlpBounds.y); + setting = config_setting_add(root, "w", CONFIG_TYPE_INT); + config_setting_set_int(setting, mc->wlpBounds.w); + setting = config_setting_add(root, "h", CONFIG_TYPE_INT); + config_setting_set_int(setting, mc->wlpBounds.h); + + char path[PATH_MAX]; + getMonitorCfgPath(path, name); + + if (!config_write_file(&cfg, path)) + { + fprintf(stderr, "Error while writing file.\n"); + config_destroy(&cfg); + } + + config_destroy(&cfg); +} + +int loadMonitorConfig(const char *name, MonitorConfig *mc) +{ + mc->loaded = 0; + + config_t cfg; + config_setting_t *root, *setting; + + char path[PATH_MAX]; + getMonitorCfgPath(path, name); + + if (!g_file_test(path, G_FILE_TEST_IS_REGULAR | G_FILE_TEST_EXISTS)) + { + generateEmptyMonitorConfig(mc); + saveMonitorConfig(name, mc); + return 1; + } + + config_init(&cfg); + if (config_read_file(&cfg, path) == CONFIG_FALSE) return 0; + root = config_root_setting(&cfg); + + setting = config_setting_get_member(root, "wlpName"); + strcpy(mc->wlpName, config_setting_get_string(setting)); + + setting = config_setting_get_member(root, "x"); + mc->wlpBounds.x = config_setting_get_int(setting); + setting = config_setting_get_member(root, "y"); + mc->wlpBounds.y = config_setting_get_int(setting); + setting = config_setting_get_member(root, "w"); + mc->wlpBounds.w = config_setting_get_int(setting); + setting = config_setting_get_member(root, "h"); + mc->wlpBounds.h = config_setting_get_int(setting); + + config_destroy(&cfg); + + mc->loaded = 1; + return 1; +} + +static void useDefaultAppCfg(AppConfig *ac) +{ +#ifdef __LINUX + ac->drawOnRootWindow = 0; +#endif + ac->targetFps = 60; + strcpy(ac->renderQuality, "best"); +} + +void saveAppConfig(AppConfig *ac) +{ + config_t cfg; + config_setting_t *root, *setting; + + config_init(&cfg); + root = config_root_setting(&cfg); + +#ifdef __LINUX + setting = config_setting_add(root, "draw_on_rootwindow", CONFIG_TYPE_INT); + config_setting_set_int(setting, ac->drawOnRootWindow); +#endif + setting = config_setting_add(root, "target_fps", CONFIG_TYPE_INT); + config_setting_set_int(setting, ac->targetFps); + setting = config_setting_add(root, "render_quality", CONFIG_TYPE_STRING); + config_setting_set_string(setting, ac->renderQuality); + + char path[PATH_MAX]; + getAppCfgPath(path); + + if (!config_write_file(&cfg, path)) + { + fprintf(stderr, "Error while writing file.\n"); + config_destroy(&cfg); + } + + config_destroy(&cfg); +} + +int loadAppConfig(AppConfig *ac) +{ + config_t cfg; + config_setting_t *root, *setting; + + char path[PATH_MAX]; + getAppCfgPath(path); + + config_init(&cfg); + if (config_read_file(&cfg, path) == CONFIG_FALSE) + { + useDefaultAppCfg(ac); + return 1; + } + root = config_root_setting(&cfg); + +#ifdef __LINUX + setting = config_setting_get_member(root, "draw_on_rootwindow"); + ac->drawOnRootWindow = config_setting_get_int(setting); +#endif + setting = config_setting_get_member(root, "target_fps"); + ac->targetFps = config_setting_get_int(setting); + setting = config_setting_get_member(root, "render_quality"); + strcpy(ac->renderQuality, config_setting_get_string(setting)); + + config_destroy(&cfg); + + return 1; +} + +int loadWallpaperConfig(const char *dirPath, WallpaperConfig *wc) +{ + wc->loaded = 0; + + config_t cfg; + config_setting_t *root, *setting; + + config_init(&cfg); + + char path[PATH_MAX]; + getWlpCfgPath(path, dirPath); + + if (config_read_file(&cfg, path) == CONFIG_FALSE) + { + getWlpCfgPath(path, dirPath); + if (config_read_file(&cfg, path) == CONFIG_FALSE) return 0; + } + root = config_root_setting(&cfg); + + setting = config_setting_get_member(root, "count"); + wc->layersCount = config_setting_get_int(setting); + setting = config_setting_get_member(root, "repeat_x"); + wc->repeatX = config_setting_get_int(setting); + setting = config_setting_get_member(root, "repeat_y"); + wc->repeatY = config_setting_get_int(setting); + + wc->layerConfigs = malloc(wc->layersCount * sizeof(LayerConfig)); + + setting = config_setting_get_member(root, "movement_x"); + float movX = config_setting_get_float(setting); + setting = config_setting_get_member(root, "movement_y"); + float movY = config_setting_get_float(setting); + + for (int i = 0; i < wc->layersCount; i++) + { + LayerConfig *lc = wc->layerConfigs + i; + + lc->sensitivityX = movX * i; + lc->sensitivityY = movY * i; + } + + config_destroy(&cfg); + + wc->loaded = 1; + + return 1; +} diff --git a/src/common/monitorScanner.c b/src/common/monitorScanner.c new file mode 100644 index 0000000..dac0208 --- /dev/null +++ b/src/common/monitorScanner.c @@ -0,0 +1,81 @@ +#include +#include + +#include "../common.h" + +#ifdef __WIN32 +#include +#else +#include +#include +#endif + +#ifdef __WIN32 +int monitorEnumIndex = 0; + +static BOOL monitorenumproc(HMONITOR monitor, HDC hdc, LPRECT rect, LPARAM param) +{ + MONITORINFO info; + info.cbSize = sizeof(MONITORINFO); + + GetMonitorInfo(monitor, &info); + + MonitorInfo *mi = (MonitorInfo *)param + monitorEnumIndex; + + snprintf( + mi->name, + MONITOR_NAME_MAX, + "Monitor %d%s", + monitorEnumIndex + 1, + info.dwFlags == MONITORINFOF_PRIMARY ? " (main)" : "" + ); + mi->bounds.x = info.rcWork.left; + mi->bounds.y = info.rcWork.top; + mi->bounds.w = info.rcWork.right - info.rcWork.left; + mi->bounds.h = info.rcWork.bottom - info.rcWork.top; + mi->config.loaded = 0; + + monitorEnumIndex++; + return TRUE; +} +#endif + +MonitorInfo *scanMonitors(int *count) +{ + MonitorInfo *m = NULL; + +#ifdef __WIN32 + monitorEnumIndex = 0; + *count = GetSystemMetrics(SM_CMONITORS); + m = malloc(sizeof(MonitorInfo) * (*count)); + + EnumDisplayMonitors(NULL, NULL, &monitorenumproc, (LPARAM)m); + +#else + int monitorCount; + + Display *display = XOpenDisplay((getenv("DISPLAY"))); + Window wnd = DefaultRootWindow(display); + XRRMonitorInfo *info = XRRGetMonitors(display, wnd, 0, &monitorCount); + + m = malloc(sizeof(MonitorInfo) * monitorCount); + + int i = 0; + while (i < monitorCount) + { + snprintf(m[i].name, MONITOR_NAME_MAX, "%s", XGetAtomName(display, info->name)); + m[i].bounds.x = info->x; + m[i].bounds.y = info->y; + m[i].bounds.w = info->width; + m[i].bounds.h = info->height; + m[i].config.loaded = 0; + + info++; + i++; + } + + *count = monitorCount; + +#endif + return m; +} diff --git a/src/common/paths.c b/src/common/paths.c new file mode 100644 index 0000000..1eeb430 --- /dev/null +++ b/src/common/paths.c @@ -0,0 +1,120 @@ +#include +#include +#include +#include + +#include "../common.h" + +void createUserDirs() +{ +#ifdef __WIN32 + const char *format = "%s\\%s"; +#else + const char *format = "%s/%s"; +#endif + + char path[PATH_MAX]; + + getAppDir(path, APP_DIR_USER_SETTINGS); + sprintf(path, format, path, "wallpapers"); + g_mkdir_with_parents(path, 484); + + getAppDir(path, APP_DIR_USER_SETTINGS); + sprintf(path, format, path, "monitors"); + g_mkdir_with_parents(path, 484); +} + +static void removeLastPathEntry(char *path) +{ + char *ptr = path + strlen(path) - 1; + while (*ptr != '\\') ptr--; + *ptr = '\0'; +} + +void getAppDir(char *buff, int type) +{ +#ifdef __LINUX + + char prefix[PATH_MAX]; + + char *prefixEnv = getenv("LWP_PREFIX"); + strcpy(prefix, prefixEnv ? prefixEnv : DEFAULT_LINUX_PREFIX); + +#endif + + if (type == APP_DIR_USER_SETTINGS) + { +#ifdef __LINUX + sprintf(buff, "%s/.config/lwp", g_get_home_dir()); +#elif __WIN32 + sprintf(buff, "%s\\lwp", g_get_user_data_dir()); +#endif + } + +#ifdef __LINUX + if (type == APP_DIR_BIN) + { + sprintf(buff, "%s/%s", prefix, "bin"); + } + else if (type == APP_DIR_SHARE) + { + sprintf(buff, "%s/%s", prefix, "share/lwp"); + } +#elif __WIN32 + if (type == APP_DIR_BIN || type == APP_DIR_SHARE) + { + GetModuleFileNameA(NULL, buff, PATH_MAX); + removeLastPathEntry(buff); + } +#endif +} + +void getMonitorCfgPath(char *buff, const char *name) +{ + getAppDir(buff, APP_DIR_USER_SETTINGS); + +#ifdef __WIN32 + const char *format = "%s\\monitors\\%s.cfg"; +#else + const char *format = "%s/monitors/%s.cfg"; +#endif + + sprintf(buff, format, buff, name); +} + +void getWlpCfgPath(char *buff, const char *dirPath) +{ +#ifdef __WIN32 + const char *format = "%s\\wallpaper.cfg"; +#else + const char *format = "%s/wallpaper.cfg"; +#endif + + sprintf(buff, format, dirPath); +} + +void getAppCfgPath(char *buff) +{ + getAppDir(buff, APP_DIR_USER_SETTINGS); + +#ifdef __WIN32 + const char *format = "%s\\lwp.cfg"; +#else + const char *format = "%s/lwp.cfg"; +#endif + + sprintf(buff, format, buff); +} + +void getLogPath(char *buff) +{ + getAppDir(buff, APP_DIR_USER_SETTINGS); + +#ifdef __WIN32 + const char *format = "%s\\log.txt"; +#else + const char *format = "%s/log"; +#endif + + sprintf(buff, format, buff); +} diff --git a/src/common/wallpaperScanner.c b/src/common/wallpaperScanner.c new file mode 100644 index 0000000..c45f60e --- /dev/null +++ b/src/common/wallpaperScanner.c @@ -0,0 +1,68 @@ +#include +#include + +#include "../common.h" + +#define WALLPAPERS_SYSTEM 0 +#define WALLPAPERS_USER 1 + +WallpaperInfo *scanWallpapers(int *count) +{ + *count = 0; + +#ifdef __WIN32 + const char *format = "%s\\%s"; +#else + const char *format = "%s/%s"; +#endif + + char userWlpPath[PATH_MAX]; + getAppDir(userWlpPath, APP_DIR_USER_SETTINGS); + sprintf(userWlpPath, format, userWlpPath, "wallpapers"); + + char systemWlpPath[PATH_MAX]; + getAppDir(systemWlpPath, APP_DIR_SHARE); + sprintf(systemWlpPath, format, systemWlpPath, "wallpapers"); + + GDir *dir; + GError *error; + const gchar *filename; + + dir = g_dir_open(systemWlpPath, 0, &error); + while ((g_dir_read_name(dir))) (*count)++; + dir = g_dir_open(userWlpPath, 0, &error); + while ((g_dir_read_name(dir))) (*count)++; + + WallpaperInfo *list = malloc(sizeof(WallpaperInfo) * (*count)); + WallpaperInfo *ptr = list; + + dir = g_dir_open(systemWlpPath, 0, &error); + while ((filename = g_dir_read_name(dir))) + { + sprintf(ptr->name, "%s", filename); +#ifdef __WIN32 + sprintf(ptr->dirPath, "%s\\%s", systemWlpPath, filename); +#else + sprintf(ptr->dirPath, "%s/%s", systemWlpPath, filename); +#endif + ptr->isDefault = 1; + ptr->config.loaded = 0; + ptr++; + } + + dir = g_dir_open(userWlpPath, 0, &error); + while ((filename = g_dir_read_name(dir))) + { + sprintf(ptr->name, "%s", filename); +#ifdef __WIN32 + sprintf(ptr->dirPath, "%s\\%s", userWlpPath, filename); +#else + sprintf(ptr->dirPath, "%s/%s", userWlpPath, filename); +#endif + ptr->isDefault = 0; + ptr->config.loaded = 0; + ptr++; + } + + return list; +} diff --git a/src/core/CMakeLists.txt b/src/core/CMakeLists.txt new file mode 100644 index 0000000..b0eaa33 --- /dev/null +++ b/src/core/CMakeLists.txt @@ -0,0 +1,70 @@ +set(_SOURCE_FILES + ../common/paths.c + ../common/config.c + ../common/wallpaperScanner.c + ../common/monitorScanner.c + main.c + windowHandlers.c + wlp.c + trayIcon.c +) + +# Windows resource file +if(_UNAME STREQUAL "WIN32") + if(MINGW) + set(CMAKE_RC_COMPILER_INIT windres) + ENABLE_LANGUAGE(RC) + SET(CMAKE_RC_COMPILE_OBJECT + " -O coff -i -o ") + endif(MINGW) + + configure_file(${CMAKE_CURRENT_SOURCE_DIR}/resource.template.rc ${CMAKE_CURRENT_SOURCE_DIR}/resource.rc + @ONLY) + list(APPEND _SOURCE_FILES "resource.rc") +endif() + +find_package (PkgConfig REQUIRED) + +if (_UNAME STREQUAL "LINUX") + # X11 and Xrandr dependency + include(FindX11) + + list(APPEND _INCLUDE_DIRS ${X11_INCLUDE_DIR}) + list(APPEND _LIBS ${X11_LIBRARIES}) + + list(APPEND _INCLUDE_DIRS ${X11_Xrandr_INCLUDE_PATH}) + list(APPEND _LIBS ${X11_Xrandr_LIB}) +endif() + +# GTK dependency +pkg_check_modules (GTK3 REQUIRED gtk+-3.0) +list(APPEND _INCLUDE_DIRS ${GTK3_INCLUDE_DIRS}) +list(APPEND _LIBS ${GTK3_LINK_LIBRARIES}) + +# libconfig dependency +pkg_check_modules (libconfig REQUIRED libconfig) +list(APPEND _INCLUDE_DIRS ${libconfig_INCLUDE_DIRS}) +list(APPEND _LIBS ${libconfig_LINK_LIBRARIES}) + +# Main executable +if(_UNAME STREQUAL "WIN32") + add_executable(lwp WIN32 ${_SOURCE_FILES}) +else() + add_executable(lwp ${_SOURCE_FILES}) +endif() + +set_target_properties(lwp PROPERTIES ENABLE_EXPORTS on) + +target_compile_definitions(lwp PUBLIC __${_UNAME} PROGRAM_VERSION="${PROGRAM_VERSION}") +target_include_directories(lwp PUBLIC ${_INCLUDE_DIRS}) +target_link_libraries(lwp PRIVATE ${_LIBS}) + +# Installation rules +if(_UNAME STREQUAL "WIN32") + install(TARGETS lwp + DESTINATION .) +elseif(_UNAME STREQUAL "LINUX") + install(TARGETS lwp + DESTINATION bin) +endif() + diff --git a/src/core/main.c b/src/core/main.c new file mode 100644 index 0000000..0ecca84 --- /dev/null +++ b/src/core/main.c @@ -0,0 +1,167 @@ +#include "main.h" + +#include "../platform_guard.h" + +GtkApplication *app = NULL; +GtkBuilder *builder = NULL; + +GtkWidget *mainWnd = NULL; +GtkWidget *exitDialog = NULL; +GtkWidget *wallpaperMgrWnd = NULL; +GtkWidget *monitorWnd = NULL; +GtkWidget *monitorListBox = NULL; +GtkWidget *wallpaperListBox = NULL; +GtkWidget *wallpaperComboBox = NULL; +GtkWidget *xPosSpinBtn = NULL; +GtkWidget *yPosSpinBtn = NULL; +GtkWidget *widthSpinBtn = NULL; +GtkWidget *heightSpinBtn = NULL; +GtkWidget *monitorNameLabel = NULL; +GtkWidget *versionLabel = NULL; +GtkWidget *appSettingsWnd = NULL; +GtkWidget *targetFpsComboBox = NULL; +GtkWidget *renderQualityComboBox = NULL; +GtkWidget *drawOnRootWndComboBox = NULL; + +static void reloadMonitorListBox() +{ + GList *rows = gtk_container_get_children(GTK_CONTAINER(monitorListBox)); + + GList *ptr = rows; + while (ptr) + { + gtk_container_remove(GTK_CONTAINER(monitorListBox), ptr->data); + ptr = ptr->next; + } + + g_list_free(rows); + + char iconPath[PATH_MAX]; + getAppDir(iconPath, APP_DIR_SHARE); +#ifdef __WIN32 + const char *format = "%s\\%s\\%s\\%s"; +#else + const char *format = "%s/%s/%s/%s"; +#endif + sprintf( + iconPath, format, iconPath, "window_templates", "assets", "screen-monitor-svgrepo-com.svg" + ); + + int monitorsCount; + MonitorInfo *monitors; + + monitors = scanMonitors(&monitorsCount); + + for (int i = 0; i < monitorsCount; i++) + { + char resStr[12]; + sprintf(resStr, "%dx%d", monitors[i].bounds.w, monitors[i].bounds.h); + + GtkWidget *nameLabel = gtk_label_new(monitors[i].name); + GtkWidget *resLabel = gtk_label_new(resStr); + GtkWidget *icon = gtk_image_new_from_file(iconPath); + + GtkWidget *labelBox = gtk_box_new(GTK_ORIENTATION_VERTICAL, 0); + gtk_container_add(GTK_CONTAINER(labelBox), nameLabel); + gtk_container_add(GTK_CONTAINER(labelBox), resLabel); + gtk_box_set_child_packing(GTK_BOX(labelBox), nameLabel, 1, 1, 0, GTK_PACK_START); + + GtkWidget *box = gtk_box_new(GTK_ORIENTATION_HORIZONTAL, 0); + gtk_container_add(GTK_CONTAINER(box), icon); + gtk_container_add(GTK_CONTAINER(box), labelBox); + gtk_box_set_child_packing(GTK_BOX(box), labelBox, 1, 1, 0, GTK_PACK_START); + + GtkWidget *row = gtk_list_box_row_new(); + gtk_container_add(GTK_CONTAINER(row), box); + + gtk_list_box_insert(GTK_LIST_BOX(monitorListBox), row, 0); + + char *nameBuff = malloc(sizeof(strlen(monitors[i].name))); + strcpy(nameBuff, monitors[i].name); + g_object_set_data(G_OBJECT(row), "monitor_name", (gpointer)nameBuff); + + gtk_widget_show_all(row); + } +} + +static void activate(GtkApplication *app, gpointer userdata) +{ + static int alreadyRunning = 0; + + if (!alreadyRunning) + { + char gladefilePath[PATH_MAX]; + getAppDir(gladefilePath, APP_DIR_SHARE); +#ifdef __WIN32 + const char *format = "%s\\window_templates\\main.glade"; +#else + const char *format = "%s/window_templates/main.glade"; +#endif + sprintf(gladefilePath, format, gladefilePath); + + builder = gtk_builder_new_from_file(gladefilePath); + gtk_builder_connect_signals(builder, NULL); + + mainWnd = (GtkWidget *)gtk_builder_get_object(builder, "MainWindow"); + exitDialog = (GtkWidget *)gtk_builder_get_object(builder, "ExitDialog"); + wallpaperMgrWnd = (GtkWidget *)gtk_builder_get_object(builder, "WallpaperManagerWindow"); + monitorWnd = (GtkWidget *)gtk_builder_get_object(builder, "MonitorWindow"); + appSettingsWnd = (GtkWidget *)gtk_builder_get_object(builder, "SettingsWindow"); + monitorListBox = (GtkWidget *)gtk_builder_get_object(builder, "MainWindow_MonitorListBox"); + versionLabel = (GtkWidget *)gtk_builder_get_object(builder, "MainWindow_VersionLabel"); + wallpaperListBox = + (GtkWidget *)gtk_builder_get_object(builder, "WallpaperManagerWindow_WallpaperListBox"); + wallpaperComboBox = + (GtkWidget *)gtk_builder_get_object(builder, "MonitorWindow_WallpaperComboBox"); + xPosSpinBtn = (GtkWidget *)gtk_builder_get_object(builder, "MonitorWindow_XPosSpinBtn"); + yPosSpinBtn = (GtkWidget *)gtk_builder_get_object(builder, "MonitorWindow_YPosSpinBtn"); + widthSpinBtn = (GtkWidget *)gtk_builder_get_object(builder, "MonitorWindow_WidthSpinBtn"); + heightSpinBtn = (GtkWidget *)gtk_builder_get_object(builder, "MonitorWindow_HeightSpinBtn"); + monitorNameLabel = + (GtkWidget *)gtk_builder_get_object(builder, "MonitorWindow_MonitorNameLabel"); + targetFpsComboBox = + (GtkWidget *)gtk_builder_get_object(builder, "SettingsWindow_TargetFpsComboBox"); + renderQualityComboBox = + (GtkWidget *)gtk_builder_get_object(builder, "SettingsWindow_TexFilteringComboBox"); + drawOnRootWndComboBox = + (GtkWidget *)gtk_builder_get_object(builder, "SettingsWindow_DrawOnRootWndComboBox"); + + gtk_window_set_application(GTK_WINDOW(mainWnd), GTK_APPLICATION(app)); + gtk_window_set_application(GTK_WINDOW(exitDialog), GTK_APPLICATION(app)); + gtk_window_set_application(GTK_WINDOW(wallpaperMgrWnd), GTK_APPLICATION(app)); + gtk_window_set_application(GTK_WINDOW(monitorWnd), GTK_APPLICATION(app)); + gtk_window_set_application(GTK_WINDOW(appSettingsWnd), GTK_APPLICATION(app)); + + gtk_label_set_text(GTK_LABEL(versionLabel), PROGRAM_VERSION); + + runWlp(); + } + + reloadMonitorListBox(); + + if (alreadyRunning) gtk_widget_set_visible(mainWnd, 1); + + alreadyRunning = 1; +} + +int main(int argc, char *argv[]) +{ + int status; + + createUserDirs(); + +#ifdef __WIN32 + initTrayIcon(); +#endif + + app = gtk_application_new("com.github.jszczerbinsky.lwp", G_APPLICATION_DEFAULT_FLAGS); + g_signal_connect(app, "activate", G_CALLBACK(activate), NULL); + status = g_application_run(G_APPLICATION(app), argc, argv); + g_object_unref(app); + +#ifdef __WIN32 + removeTrayIcon(); +#endif + + return status; +} diff --git a/src/core/main.h b/src/core/main.h new file mode 100644 index 0000000..7b9697f --- /dev/null +++ b/src/core/main.h @@ -0,0 +1,40 @@ +#ifndef MAIN_H +#define MAIN_H + +#include + +// G_APPLICATION_DEFAULT_FLAGS doesn't exist in older versions of glib +#ifndef G_APPLICATION_DEFAULT_FLAGS +#define G_APPLICATION_DEFAULT_FLAGS G_APPLICATION_FLAGS_NONE +#endif + +#include "../common.h" + +extern GtkApplication *app; + +extern GtkWidget *mainWnd; +extern GtkWidget *exitDialog; +extern GtkWidget *wallpaperMgrWnd; +extern GtkWidget *monitorWnd; +extern GtkWidget *monitorListBox; +extern GtkWidget *wallpaperListBox; +extern GtkWidget *wallpaperComboBox; +extern GtkWidget *xPosSpinBtn; +extern GtkWidget *yPosSpinBtn; +extern GtkWidget *widthSpinBtn; +extern GtkWidget *heightSpinBtn; +extern GtkWidget *monitorNameLabel; +extern GtkWidget *appSettingsWnd; +extern GtkWidget *targetFpsComboBox; +extern GtkWidget *renderQualityComboBox; +extern GtkWidget *drawOnRootWndComboBox; + +void runWlp(); +void killWlp(); + +#ifdef __WIN32 +void initTrayIcon(); +void removeTrayIcon(); +#endif + +#endif diff --git a/resource.template.rc b/src/core/resource.template.rc similarity index 91% rename from resource.template.rc rename to src/core/resource.template.rc index 892e717..16de8c9 100644 --- a/resource.template.rc +++ b/src/core/resource.template.rc @@ -3,7 +3,7 @@ #define PROGRAM_VER "@PROGRAM_VERSION@" -id ICON "icon.ico" +id ICON "..\..\icon.ico" VS_VERSION_INFO VERSIONINFO FILEOS VOS_NT @@ -19,7 +19,7 @@ BEGIN VALUE "FileVersion", PROGRAM_VER VALUE "InternalName", "Layered WallPaper" VALUE "LegalCopyright", "(c) 2022 Jakub Szczerbiński" - VALUE "OriginalFilename", "lwp.exe" + VALUE "OriginalFilename", "lwpwlp.exe" VALUE "ProductName", "Layered WallPaper" VALUE "ProductVersion", PROGRAM_VER END diff --git a/src/core/trayIcon.c b/src/core/trayIcon.c new file mode 100644 index 0000000..e4d1473 --- /dev/null +++ b/src/core/trayIcon.c @@ -0,0 +1,78 @@ +#ifdef __WIN32 + +#include +#include +#include + +#include "main.h" + +#define WM_TRAY_ICON (WM_USER + 1) + +static NOTIFYICONDATA nid; + +void removeTrayIcon() { Shell_NotifyIcon(NIM_DELETE, &nid); } + +int updateTrayIcon() +{ + MSG msg; + while (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE)) + { + TranslateMessage(&msg); + DispatchMessage(&msg); + } + + return 1; +} + +static LRESULT CALLBACK wndProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam) +{ + switch (uMsg) + { + case WM_TRAY_ICON: + if (lParam == WM_RBUTTONDOWN || lParam == WM_LBUTTONDOWN) + { + gtk_widget_set_visible(mainWnd, 1); + } + break; + } +} + +void initTrayIcon() +{ + // Create an invisible window to process tray icon events + + HINSTANCE hInstance = GetModuleHandle(NULL); + const TCHAR CLASS_NAME[] = TEXT("Hidden Window"); + WNDCLASS wc; + memset(&wc, 0, sizeof(WNDCLASS)); + wc.lpfnWndProc = wndProc; + wc.hInstance = hInstance; + wc.lpszClassName = CLASS_NAME; + RegisterClass(&wc); + HWND hWnd = CreateWindowEx( + 0, + CLASS_NAME, + TEXT(""), + WS_OVERLAPPEDWINDOW, + CW_USEDEFAULT, + CW_USEDEFAULT, + CW_USEDEFAULT, + CW_USEDEFAULT, + NULL, + NULL, + hInstance, + NULL + ); + + // Create tray icon + + nid.cbSize = sizeof(NOTIFYICONDATA); + nid.hWnd = hWnd; + nid.uCallbackMessage = WM_TRAY_ICON; + nid.hIcon = LoadIcon(hInstance, "ID"); + nid.uFlags = NIF_ICON | NIF_MESSAGE; + + Shell_NotifyIcon(NIM_ADD, &nid); +} + +#endif diff --git a/src/core/windowHandlers.c b/src/core/windowHandlers.c new file mode 100644 index 0000000..bc75cfa --- /dev/null +++ b/src/core/windowHandlers.c @@ -0,0 +1,153 @@ +#include "main.h" + +// Exit Dialog handlers + +G_MODULE_EXPORT void ExitDialogClose() { gtk_widget_set_visible(exitDialog, 0); } + +G_MODULE_EXPORT void ExitDialog_No() { gtk_widget_set_visible(exitDialog, 0); } + +G_MODULE_EXPORT void ExitDialog_Yes() +{ + killWlp(); + g_application_quit(G_APPLICATION(app)); +} + +// Main Window handlers + +G_MODULE_EXPORT void MainWindow_ManageWallpapersBtnClick() +{ + GtkDialogFlags flags = GTK_DIALOG_DESTROY_WITH_PARENT; + GtkWidget *dialog = gtk_message_dialog_new (GTK_WINDOW(mainWnd), + flags, + GTK_MESSAGE_ERROR, + GTK_BUTTONS_CLOSE, + "This feature will be available in the future"); + gtk_dialog_run (GTK_DIALOG (dialog)); + gtk_widget_destroy (dialog); + //gtk_widget_set_visible(wallpaperMgrWnd, 1); +} + +G_MODULE_EXPORT void MainWindow_MonitorEditBtnClick() { gtk_widget_set_visible(monitorWnd, 1); } + +G_MODULE_EXPORT void MainWindow_ExitBtnClick() { gtk_widget_set_visible(exitDialog, 1); } + +G_MODULE_EXPORT void MainWindow_AppSettingsBtnClick() { gtk_widget_set_visible(appSettingsWnd, 1); } + +G_MODULE_EXPORT void MainWindowClose() { gtk_widget_set_visible(mainWnd, 0); } + +// Wallpapaer Manager Window handlers + +G_MODULE_EXPORT void WallpaperManagerWindowClose() { gtk_widget_set_visible(wallpaperMgrWnd, 0); } + +G_MODULE_EXPORT void WallpaperManagerWindowShow() +{ + int wlpCount; + WallpaperInfo *wlpList = scanWallpapers(&wlpCount); + + for (int i = 0; i < wlpCount; i++) + { + GtkWidget *label = gtk_label_new(wlpList[i].name); + GtkWidget *row = gtk_list_box_row_new(); + gtk_container_add(GTK_CONTAINER(row), label); + + gtk_list_box_insert(GTK_LIST_BOX(wallpaperListBox), row, 0); + gtk_widget_show_all(row); + } + + free(wlpList); +} + +// Monitor Window handlers + +G_MODULE_EXPORT void MonitorWindowClose() { gtk_widget_set_visible(monitorWnd, 0); } +G_MODULE_EXPORT void MonitorWindowShow() +{ + // Clear wallpaper list + gtk_combo_box_text_remove_all(GTK_COMBO_BOX_TEXT(wallpaperComboBox)); + + // Load wallpaper list + int wlpCount; + WallpaperInfo *wlpList = scanWallpapers(&wlpCount); + + for (int i = 0; i < wlpCount; i++) + { + gtk_combo_box_text_insert( + GTK_COMBO_BOX_TEXT(wallpaperComboBox), 0, wlpList[i].name, wlpList[i].name + ); + } + gtk_combo_box_set_active(GTK_COMBO_BOX(wallpaperComboBox), 0); + + free(wlpList); + + // Find selected monitor name + GtkListBoxRow *listBoxRow = gtk_list_box_get_selected_row(GTK_LIST_BOX(monitorListBox)); + const char *monitorName = g_object_get_data(G_OBJECT(listBoxRow), "monitor_name"); + gtk_label_set_text(GTK_LABEL(monitorNameLabel), monitorName); + + // Read configuration from config file + MonitorConfig mc; + if (loadMonitorConfig(monitorName, &mc)) + { + gtk_spin_button_set_value(GTK_SPIN_BUTTON(xPosSpinBtn), (gdouble)mc.wlpBounds.x); + gtk_spin_button_set_value(GTK_SPIN_BUTTON(yPosSpinBtn), (gdouble)mc.wlpBounds.y); + gtk_spin_button_set_value(GTK_SPIN_BUTTON(widthSpinBtn), (gdouble)mc.wlpBounds.w); + gtk_spin_button_set_value(GTK_SPIN_BUTTON(heightSpinBtn), (gdouble)mc.wlpBounds.h); + + gtk_combo_box_set_active_id(GTK_COMBO_BOX(wallpaperComboBox), mc.wlpName); + } +} + +G_MODULE_EXPORT void MonitorWindow_ApplyBtnClick() +{ + MonitorConfig mc; + strcpy(mc.wlpName, gtk_combo_box_get_active_id(GTK_COMBO_BOX(wallpaperComboBox))); + mc.wlpBounds.x = gtk_spin_button_get_value_as_int(GTK_SPIN_BUTTON(xPosSpinBtn)); + mc.wlpBounds.y = gtk_spin_button_get_value_as_int(GTK_SPIN_BUTTON(yPosSpinBtn)); + mc.wlpBounds.w = gtk_spin_button_get_value_as_int(GTK_SPIN_BUTTON(widthSpinBtn)); + mc.wlpBounds.h = gtk_spin_button_get_value_as_int(GTK_SPIN_BUTTON(heightSpinBtn)); + + saveMonitorConfig(gtk_label_get_text(GTK_LABEL(monitorNameLabel)), &mc); + + killWlp(); + runWlp(); +} + +G_MODULE_EXPORT void MonitorWindow_ExitBtnClick() { gtk_widget_set_visible(monitorWnd, 0); } + +// App Settings Window handlers + +G_MODULE_EXPORT void SettingsWindowShow() +{ + AppConfig ac; + loadAppConfig(&ac); + + char targetFpsStr[4]; + sprintf(targetFpsStr, "%d", ac.targetFps); + +#ifdef __LINUX + char drawOnRootWindowStr[2]; + sprintf(drawOnRootWindowStr, "%d", ac.drawOnRootWindow); +#else + char *drawOnRootWindowStr = "0"; +#endif + gtk_combo_box_set_active_id(GTK_COMBO_BOX(renderQualityComboBox), ac.renderQuality); + gtk_combo_box_set_active_id(GTK_COMBO_BOX(targetFpsComboBox), targetFpsStr); + gtk_combo_box_set_active_id(GTK_COMBO_BOX(drawOnRootWndComboBox), drawOnRootWindowStr); +} + +G_MODULE_EXPORT void SettingsWindowClose() { gtk_widget_set_visible(appSettingsWnd, 0); } + +G_MODULE_EXPORT void SettingsWindow_ApplyBtnClick() +{ + AppConfig ac; + strcpy(ac.renderQuality, gtk_combo_box_get_active_id(GTK_COMBO_BOX(renderQualityComboBox))); + ac.targetFps = atoi(gtk_combo_box_get_active_id(GTK_COMBO_BOX(targetFpsComboBox))); + ac.drawOnRootWindow = atoi(gtk_combo_box_get_active_id(GTK_COMBO_BOX(drawOnRootWndComboBox))); + + saveAppConfig(&ac); + + killWlp(); + runWlp(); +} + +G_MODULE_EXPORT void SettingsWindow_ExitBtnClick() { gtk_widget_set_visible(appSettingsWnd, 0); } diff --git a/src/core/wlp.c b/src/core/wlp.c new file mode 100644 index 0000000..2542599 --- /dev/null +++ b/src/core/wlp.c @@ -0,0 +1,64 @@ +#include "main.h" + +#ifdef __WIN32 +#include +#include +#else +#include +#endif + +#ifdef __WIN32 +static HANDLE hWlpProcess = NULL; +#else +static FILE *wlpProcess = NULL; +static int wlpPid = 0; +#endif + +void killWlp() +{ +#ifdef __WIN32 + TerminateProcess(hWlpProcess, 0); +#else + if (wlpPid != 0) + { + kill(wlpPid, SIGINT); + waitpid(wlpPid, NULL, 0); + } + if (wlpProcess != NULL) pclose(wlpProcess); + + wlpPid = 0; + wlpProcess = NULL; +#endif +} + +void runWlp() +{ +#ifdef __WIN32 + STARTUPINFO si; + PROCESS_INFORMATION pi; + + ZeroMemory(&si, sizeof(si)); + ZeroMemory(&pi, sizeof(pi)); + si.cb = sizeof(si); + + TCHAR path[MAX_PATH]; + GetModuleFileName(NULL, path, MAX_PATH); + path[_tcslen(path) - 4] = '\0'; + _tcscat(path, TEXT("wlp.exe")); + + if (CreateProcess(NULL, path, NULL, NULL, FALSE, 0, NULL, NULL, &si, &pi)) + hWlpProcess = pi.hProcess; + else + printf("Failed to start a wallpaper subprocess"); + +#else + char path[PATH_MAX]; + getAppDir(path, APP_DIR_BIN); + strcat(path, "/lwpwlp"); + + wlpProcess = popen(path, "r"); + char buff[10]; + fgets(buff, sizeof(buff) - 1, wlpProcess); + wlpPid = atoi(buff); +#endif +} diff --git a/platform_guard.h b/src/platform_guard.h similarity index 54% rename from platform_guard.h rename to src/platform_guard.h index 23b647c..2b1dda8 100644 --- a/platform_guard.h +++ b/src/platform_guard.h @@ -2,13 +2,11 @@ #define PLATFORM_GUARD_H #ifndef __WIN32 -#ifndef __DARWIN #ifndef __LINUX #error "Unsupported platform." -#endif // __LINUX -#endif // __DARWIN -#endif // __WIN32 +#endif // __LINUX +#endif // __WIN32 -#endif // PLATFORM_GUARD_H +#endif // PLATFORM_GUARD_H diff --git a/src/window_templates/assets/cross-close-svgrepo-com.svg b/src/window_templates/assets/cross-close-svgrepo-com.svg new file mode 100644 index 0000000..a2846fe --- /dev/null +++ b/src/window_templates/assets/cross-close-svgrepo-com.svg @@ -0,0 +1,7 @@ + + + + + + + \ No newline at end of file diff --git a/src/window_templates/assets/github-svgrepo-com.svg b/src/window_templates/assets/github-svgrepo-com.svg new file mode 100644 index 0000000..c0a813f --- /dev/null +++ b/src/window_templates/assets/github-svgrepo-com.svg @@ -0,0 +1,7 @@ + + + + + + + \ No newline at end of file diff --git a/src/window_templates/assets/image-photo-svgrepo-com.svg b/src/window_templates/assets/image-photo-svgrepo-com.svg new file mode 100644 index 0000000..a924c43 --- /dev/null +++ b/src/window_templates/assets/image-photo-svgrepo-com.svg @@ -0,0 +1,7 @@ + + + + + + + \ No newline at end of file diff --git a/src/window_templates/assets/question-svgrepo-com.svg b/src/window_templates/assets/question-svgrepo-com.svg new file mode 100644 index 0000000..b29ae56 --- /dev/null +++ b/src/window_templates/assets/question-svgrepo-com.svg @@ -0,0 +1,7 @@ + + + + + + + \ No newline at end of file diff --git a/src/window_templates/assets/screen-monitor-svgrepo-com.svg b/src/window_templates/assets/screen-monitor-svgrepo-com.svg new file mode 100644 index 0000000..439637c --- /dev/null +++ b/src/window_templates/assets/screen-monitor-svgrepo-com.svg @@ -0,0 +1,7 @@ + + + + + + + \ No newline at end of file diff --git a/src/window_templates/assets/settings-svgrepo-com.svg b/src/window_templates/assets/settings-svgrepo-com.svg new file mode 100644 index 0000000..be067f1 --- /dev/null +++ b/src/window_templates/assets/settings-svgrepo-com.svg @@ -0,0 +1,10 @@ + + + + + + + + + + \ No newline at end of file diff --git a/src/window_templates/main.glade b/src/window_templates/main.glade new file mode 100644 index 0000000..e3147ed --- /dev/null +++ b/src/window_templates/main.glade @@ -0,0 +1,1116 @@ + + + + + + + False + Closing Layered WallPaper + False + 480 + 100 + assets/question-svgrepo-com.svg + dialog + False + + + + False + vertical + 2 + + + False + end + + + Yes + True + True + True + + + + True + True + 0 + + + + + No + True + True + True + + + + True + True + 1 + + + + + False + False + 0 + + + + + True + False + + + True + False + assets/question-svgrepo-com.svg + + + False + True + 0 + + + + + True + False + Are you sure, you want to close Layered WallPaper? + + + False + True + 1 + + + + + True + True + 1 + + + + + + + 10000 + 1 + 10 + + + False + Layered WallPaper Settings + False + 800 + 600 + + + + True + False + 40 + 40 + vertical + + + True + False + vertical + + + True + False + 10 + 10 + Layered WallPaper + center + + + + + + + False + True + 0 + + + + + True + False + Enhance your desktop experiance + center + + + + + + False + True + 1 + + + + + False + True + 0 + + + + + True + False + 30 + + + True + False + 40 + 40 + vertical + + + True + False + 5 + 15 + Setup your monitors + + + + + + False + True + 0 + + + + + True + False + + + True + True + + + True + False + + + True + False + 10 + assets/screen-monitor-svgrepo-com.svg + 6 + + + False + True + 0 + + + + + True + False + vertical + + + True + False + HDMI-1 + + + True + True + 0 + + + + + True + False + 1920x1080 + + + False + True + 1 + + + + + True + True + 1 + + + + + + + + + True + True + + + True + False + + + True + False + 10 + assets/screen-monitor-svgrepo-com.svg + 6 + + + False + True + 0 + + + + + True + False + vertical + + + True + False + HDMI-1 + + + + + + True + True + 0 + + + + + True + False + 1920x1080 + + + False + True + 1 + + + + + True + True + 1 + + + + + + + + + False + True + 1 + + + + + Edit settings + True + True + True + 10 + + + + False + True + 2 + + + + + True + True + 0 + + + + + True + False + center + vertical + 10 + + + True + True + True + + + + True + False + vertical + + + True + False + 20 + assets/image-photo-svgrepo-com.svg + 6 + + + True + True + 0 + + + + + True + False + 15 + 15 + Manage +wallpapers + center + + + False + True + end + 1 + + + + + + + False + True + 0 + + + + + True + True + True + + + + True + False + vertical + + + True + False + 20 + assets/settings-svgrepo-com.svg + 6 + + + True + True + 0 + + + + + True + False + 15 + 15 + Application +settings + center + + + False + True + end + 1 + + + + + + + False + True + 1 + + + + + True + True + True + + + + True + False + vertical + + + True + False + 20 + assets/cross-close-svgrepo-com.svg + 6 + + + True + True + 0 + + + + + True + False + 15 + 15 + Turn off +Layered WallPaper + center + + + False + True + end + 1 + + + + + + + False + True + 2 + + + + + False + True + end + 1 + + + + + True + True + 1 + + + + + True + False + 20 + + + True + False + 11 + v 1.0.0 + + + False + True + 1 + + + + + Github page + True + True + True + none + https://github.com/jszczerbinsky/lwp + + + False + True + end + 1 + + + + + False + True + end + 2 + + + + + + + False + False + 500 + 250 + + + + + True + False + vertical + + + True + False + center + + + True + False + assets/settings-svgrepo-com.svg + + + False + True + 0 + + + + + True + False + 10 + 10 + Application settings + center + + + + + + False + True + 1 + + + + + False + True + 0 + + + + + + True + False + 20 + 20 + 15 + True + True + + + True + False + start + Target FPS + + + 0 + 0 + + + + + True + False + start + Texture filtering + + + 0 + 1 + + + + + True + False + + Anisotropic + Linear + Nearest-neighbour + + + + 1 + 1 + + + + + True + False + start + Draw on root window (Linux only) + + + 0 + 2 + + + + + True + False + + No + Yes + + + + 1 + 2 + + + + + True + False + + 30 fps + 60 fps + 120 fps + 144 fps + 240 fps + + + + 1 + 0 + + + + + False + True + 1 + + + + + True + False + center + 20 + 20 + 50 + True + + + Apply + True + True + True + + + + False + True + 0 + + + + + Exit + True + True + True + + + + False + True + 1 + + + + + False + True + end + 2 + + + + + + + False + Wallpaper Manager + 800 + 600 + assets/image-photo-svgrepo-com.svg + + + + + True + False + vertical + + + True + False + 10 + 10 + Manage wallpapers + + + + + + False + True + 0 + + + + + True + False + + + False + True + 1 + + + + + True + False + center + + + Add + True + True + True + + + False + True + 0 + + + + + Remove + True + True + True + + + False + True + 1 + + + + + False + True + end + 2 + + + + + + + 10000 + 1 + 10 + + + -10000 + 10000 + 1 + 10 + + + -10000 + 10000 + 1 + 10 + + + False + Monitor Settings + 600 + 260 + assets/settings-svgrepo-com.svg + + + + + True + False + vertical + + + True + False + center + + + True + False + assets/screen-monitor-svgrepo-com.svg + + + False + True + 0 + + + + + True + False + 10 + 10 + Monitor name + center + + + + + + False + True + 1 + + + + + False + True + 0 + + + + + + True + False + 20 + 20 + 15 + True + + + True + False + 0 + + + 1 + 0 + 3 + + + + + True + False + Wallpaper + + + 0 + 0 + + + + + True + False + X position + + + 0 + 1 + + + + + True + False + Y position + + + 0 + 2 + + + + + True + False + Height + + + 2 + 2 + + + + + True + False + Width + + + 2 + 1 + + + + + True + True + 6 + 1 + number + XPosAdjustment + + + 1 + 1 + + + + + True + True + 6 + 1 + number + WidthAdjustment + + + 3 + 1 + + + + + True + True + 6 + 1 + number + HeightAdjustment + + + 3 + 2 + + + + + True + True + 6 + 1 + number + YPosAdjustment + + + 1 + 2 + + + + + False + True + 1 + + + + + True + False + center + 20 + 20 + 50 + True + + + Apply + True + True + True + + + + False + True + 0 + + + + + Exit + True + True + True + + + + False + True + 1 + + + + + False + True + end + 2 + + + + + + diff --git a/src/wlp/CMakeLists.txt b/src/wlp/CMakeLists.txt new file mode 100644 index 0000000..8055a49 --- /dev/null +++ b/src/wlp/CMakeLists.txt @@ -0,0 +1,76 @@ +if(SDL2_RUNTIME_DIR) + string(REPLACE "\\" "/" SDL2_RUNTIME_DIR ${SDL2_RUNTIME_DIR}) +endif() + +set(_SOURCE_FILES + ../common/paths.c + ../common/config.c + ../common/monitorScanner.c + ../common/wallpaperScanner.c + main.c + debug.c + render.c + window.c + ) + +# GLIB dependency +find_package(PkgConfig REQUIRED) +pkg_search_module(GLIB REQUIRED glib-2.0) +set(_INCLUDE_DIRS ${GLIB_INCLUDE_DIRS}) +set(_LIBS ${GLIB_LDFLAGS}) + +if (_UNAME STREQUAL "LINUX") + # X11 and Xrandr dependency + include(FindX11) + + list(APPEND _INCLUDE_DIRS ${X11_INCLUDE_DIR}) + list(APPEND _LIBS ${X11_LIBRARIES}) + + list(APPEND _INCLUDE_DIRS ${X11_Xrandr_INCLUDE_PATH}) + list(APPEND _LIBS ${X11_Xrandr_LIB}) +endif() + +# libconfig dependency +pkg_check_modules (libconfig REQUIRED libconfig) +list(APPEND _INCLUDE_DIRS ${libconfig_INCLUDE_DIRS}) +list(APPEND _LIBS ${libconfig_LINK_LIBRARIES}) + +# SDL2 dependency +find_package(SDL2 REQUIRED CONFIG) +list(APPEND _INCLUDE_DIRS ${SDL2_INCLUDE_DIRS}) +list(APPEND _LIBS ${SDL2_LIBRARIES}) + +if (_UNAME STREQUAL "LINUX") + # X11 dependency + find_package(X11 REQUIRED) + list(APPEND _INCLUDE_DIRS ${X11_INCLUDE_DIR}) + list(APPEND _LIBS ${X11_LIBRARIES}) +endif() + +option(LWP_INSTALL_LAUNCHD "Launch lwp on login (MacOSX only)" OFF) + +# Main executable +if(_UNAME STREQUAL "WIN32") + add_executable(lwpwlp WIN32 ${_SOURCE_FILES}) +else() + add_executable(lwpwlp ${_SOURCE_FILES}) +endif() + +# Windows specific properties for executable +if(_UNAME STREQUAL "WIN32") + set_property(TARGET lwpwlp PROPERTY VS_DPI_AWARE "PerMonitor") +endif() + +target_compile_definitions(lwpwlp PUBLIC __${_UNAME}) +target_include_directories(lwpwlp PUBLIC ${_INCLUDE_DIRS}) +target_link_libraries(lwpwlp PRIVATE ${_LIBS}) + +# Installation rules +if(_UNAME STREQUAL "WIN32") + install(TARGETS lwpwlp + DESTINATION .) +else() + install(TARGETS lwpwlp + DESTINATION bin) +endif() + diff --git a/src/wlp/debug.c b/src/wlp/debug.c new file mode 100644 index 0000000..5e51f3a --- /dev/null +++ b/src/wlp/debug.c @@ -0,0 +1,40 @@ +#include +#include +#include + +#include "main.h" + +void lwpLog(int type, const char *str, ...) +{ + char path[PATH_MAX]; + getLogPath(path); + + FILE *file = fopen(path, "a"); + + char *typePrefix; + + switch (type) + { + case LOG_ERROR: + typePrefix = "ERROR"; + break; + case LOG_INFO: + typePrefix = "INFO"; + break; + case LOG_WARNING: + typePrefix = "WARNING"; + break; + } + + fprintf(file, "%s: ", typePrefix); + + va_list args; + va_start(args, str); + vfprintf(file, str, args); + va_end(args); + + fprintf(file, "\n"); + + fclose(file); +} + diff --git a/src/wlp/main.c b/src/wlp/main.c new file mode 100644 index 0000000..b7c5196 --- /dev/null +++ b/src/wlp/main.c @@ -0,0 +1,196 @@ +#include "main.h" + +#include "../platform_guard.h" + +static App app; + +static void atExit() +{ + for (int i = 0; i < app.monitorsCount; i++) + { + Monitor *m = app.monitors + i; + if (m->tex) SDL_DestroyTexture(m->tex); + if (m->wlp.tex) SDL_DestroyTexture(m->wlp.tex); + + for (int l = 0; l < m->wlp.info.config.layersCount; l++) + SDL_DestroyTexture(m->wlp.layers[l].tex); + free(m->wlp.layers); + + m++; + } + free(app.monitors); + + if (app.renderer) SDL_DestroyRenderer(app.renderer); + if (app.window) SDL_DestroyWindow(app.window); + + SDL_Quit(); +} + +void exitSignalHandler(int s) +{ + lwpLog(LOG_INFO, "Terminating..."); + exit(0); +} + +void initWallpaper(App *app, Monitor *m, WallpaperInfo *wallpapers, int wallpapersCount) +{ + MonitorInfo *mi = &m->info; + + int foundWlp = 0; + + for (int j = 0; j < wallpapersCount; j++) + { + if (strcmp(mi->config.wlpName, wallpapers[j].name) == 0) + { + memcpy(&m->wlp.info, wallpapers + j, sizeof(WallpaperInfo)); + + if (!loadWallpaperConfig(m->wlp.info.dirPath, &m->wlp.info.config)) + { + lwpLog(LOG_WARNING, "Could not load the wallpaper config"); + } + else + { + Wallpaper *wallpaper = &m->wlp; + + lwpLog(LOG_INFO, "Initializing wallpaper %s...", wallpaper->info.name); + lwpLog(LOG_INFO, "Layers count: %d", wallpaper->info.config.layersCount); + lwpLog( + LOG_INFO, + "Repeat X Y: %d %d", + wallpaper->info.config.repeatX, + wallpaper->info.config.repeatY + ); + + m->tex = SDL_CreateTexture( + app->renderer, + SDL_PIXELFORMAT_ARGB8888, + SDL_TEXTUREACCESS_TARGET, + mi->bounds.w, + mi->bounds.h + ); + if (m->tex == NULL) + lwpLog(LOG_ERROR, "Failed creating a texture for the monitor: %s", SDL_GetError()); + + wallpaper->layers = malloc(sizeof(Layer) * wallpaper->info.config.layersCount); + wallpaper->tex = SDL_CreateTexture( + app->renderer, + SDL_PIXELFORMAT_ARGB8888, + SDL_TEXTUREACCESS_TARGET, + mi->config.wlpBounds.w, + mi->config.wlpBounds.h + ); + if (wallpaper->tex == NULL) + lwpLog(LOG_ERROR, "Failed creating a texture for the monitor: %s", SDL_GetError()); + + for (int l = 0; l < wallpaper->info.config.layersCount; l++) + { + char path[PATH_MAX]; + snprintf(path, PATH_MAX, "%s/%d.bmp", wallpaper->info.dirPath, l + 1); + + SDL_Surface *surf = SDL_LoadBMP(path); + if (!surf) lwpLog(LOG_ERROR, "File %s not found", path); + + if (l == 0) + { + wallpaper->originalW = surf->w; + wallpaper->originalH = surf->h; + } + + wallpaper->layers[l].tex = SDL_CreateTextureFromSurface(app->renderer, surf); + if (wallpaper->tex == NULL) + lwpLog(LOG_ERROR, "Failed creating a texture for the layer %d: %s", l, SDL_GetError()); + + SDL_FreeSurface(surf); + } + } + foundWlp = 1; + + break; + } + } + if (!foundWlp) lwpLog(LOG_WARNING, "Couldn't find the wallpaper. Ignoring..."); +} + +int initMonitors(App *app) +{ + MonitorInfo *monitors = scanMonitors(&app->monitorsCount); + app->monitors = malloc(sizeof(Monitor) * app->monitorsCount); + + int wallpapersCount; + WallpaperInfo *wallpapers = scanWallpapers(&wallpapersCount); + + lwpLog(LOG_INFO, "Scanner found %d monitor(s)", app->monitorsCount); + + for (int i = 0; i < app->monitorsCount; i++) + { + memcpy(&app->monitors[i].info, monitors + i, sizeof(MonitorInfo)); + app->monitors[i].tex = NULL; + + MonitorInfo *mi = &app->monitors[i].info; + + if (!loadMonitorConfig(mi->name, &mi->config)) + { + lwpLog(LOG_WARNING, "Couldn't find config file for monitor %s. Ignoring...", mi->name); + } + else + { + lwpLog(LOG_INFO, "Initializing monitor %d...", i); + lwpLog(LOG_INFO, "Wallpaper: %s", mi->config.wlpName); + lwpLog( + LOG_INFO, "Bounds: %d %d %dx%d", mi->bounds.x, mi->bounds.y, mi->bounds.w, mi->bounds.h + ); + lwpLog( + LOG_INFO, + "Wallpaper destination bounds: %d %d %dx%d", + mi->config.wlpBounds.x, + mi->config.wlpBounds.y, + mi->config.wlpBounds.w, + mi->config.wlpBounds.h + ); + + initWallpaper(app, app->monitors + i, wallpapers, wallpapersCount); + } + } + + free(wallpapers); + free(monitors); +} + +int main(int argc, char *argv[]) +{ + memset(&app, 0, sizeof(App)); + + char pidStr[10]; + sprintf(pidStr, "%d\0", getpid()); + fputs(pidStr, stdout); + printf("\n"); + fflush(stdout); + +#ifdef __WIN32 + signal(SIGTERM, exitSignalHandler); +#else + signal(SIGINT, exitSignalHandler); +#endif + + lwpLog(LOG_INFO, "Starting Layered WallPaper"); + + lwpLog(LOG_INFO, "Loading app config"); + loadAppConfig(&app.config); + + lwpLog(LOG_INFO, "Initializing SDL"); + SDL_Init(SDL_INIT_VIDEO | SDL_INIT_EVENTS); + SDL_SetHint(SDL_HINT_RENDER_SCALE_QUALITY, app.config.renderQuality); + + lwpLog(LOG_INFO, "Initializing window"); + initWindow(&app); + + lwpLog(LOG_INFO, "Initializing monitors"); + initMonitors(&app); + + atexit(atExit); + + lwpLog(LOG_INFO, "Starting wallpaper loop"); + runWallpaperLoop(&app); + + return 0; +} diff --git a/src/wlp/main.h b/src/wlp/main.h new file mode 100644 index 0000000..cdbe86b --- /dev/null +++ b/src/wlp/main.h @@ -0,0 +1,65 @@ +#ifndef MAIN_H +#define MAIN_H + +#ifdef _MSC_VER +#define PATH_MAX MAX_PATH +#include +#else +#include +#endif + +#include + +#ifdef __WIN32 +#include +#include +#elif __LINUX +#include +#include +#include +#include +#include +#endif + +#include "../common.h" + +#define LOG_ERROR 0 +#define LOG_INFO 1 +#define LOG_WARNING 2 + +typedef struct +{ + SDL_Texture *tex; +} Layer; + +typedef struct +{ + WallpaperInfo info; + int originalW; + int originalH; + SDL_Texture *tex; + Layer *layers; +} Wallpaper; + +typedef struct +{ + MonitorInfo info; + SDL_Texture *tex; + Wallpaper wlp; +} Monitor; + +typedef struct +{ + AppConfig config; + int monitorsCount; + Monitor *monitors; + SDL_Window *window; + SDL_Renderer *renderer; +} App; + +void lwpLog(int type, const char *str, ...); + +void initWindow(App *app); +void runWallpaperLoop(App *app); + +#endif // MAIN_H diff --git a/src/wlp/render.c b/src/wlp/render.c new file mode 100644 index 0000000..d0ddc5b --- /dev/null +++ b/src/wlp/render.c @@ -0,0 +1,159 @@ +#include + +#include "main.h" + +static int lerp(int a, int b, float t) +{ + if (t > 1) t = 1; + return (int)((float)a + (float)t * ((float)b - (float)a)); +} + +void runWallpaperLoop(App *app) +{ + int quit = 0; + + SDL_Event event; + + int mx = 0; + int my = 0; + + while (!quit) + { + static int currentX = 0; + static int currentY = 0; + + static int lastTicks = 0; + + int ticks = SDL_GetTicks(); + float dT = (ticks - lastTicks) / 1000.0f; + lastTicks = ticks; + +#ifdef __WIN32 + POINT mPos; + GetCursorPos(&mPos); + mx = mPos.x - GetSystemMetrics(SM_XVIRTUALSCREEN); + my = mPos.y - GetSystemMetrics(SM_YVIRTUALSCREEN); +#else + SDL_GetGlobalMouseState(&mx, &my); +#endif + + while (SDL_PollEvent(&event)) + if (event.type == SDL_QUIT) quit = 1; + + currentX = lerp(currentX, mx, dT * 4); // 4: smooth + currentY = lerp(currentY, my, dT * 4); + + for (int m = 0; m < app->monitorsCount; m++) + { + if (!app->monitors[m].info.config.loaded || !app->monitors[m].wlp.info.config.loaded) + continue; + + int relativeCurrentX = currentX - app->monitors[m].info.bounds.x; + int relativeCurrentY = currentY - app->monitors[m].info.bounds.y; + + if (relativeCurrentX < 0) relativeCurrentX = 0; + if (relativeCurrentY < 0) relativeCurrentY = 0; + if (relativeCurrentX > app->monitors[m].info.bounds.w) + relativeCurrentX = app->monitors[m].info.bounds.w; + if (relativeCurrentY > app->monitors[m].info.bounds.h) + relativeCurrentY = app->monitors[m].info.bounds.h; + + if (SDL_SetRenderTarget(app->renderer, app->monitors[m].wlp.tex) != 0) + { + lwpLog(LOG_ERROR, "Error setting the renderer target: %s", SDL_GetError()); + quit = 1; + } + SDL_RenderClear(app->renderer); + + for (int i = 0; i < app->monitors[m].wlp.info.config.layersCount; i++) + { + SDL_Rect src = { + .x = 0, + .y = 0, + .w = app->monitors[m].wlp.originalW, + .h = app->monitors[m].wlp.originalH, + }; + + int x = + -((relativeCurrentX - app->monitors[m].info.bounds.w / 2) * + app->monitors[m].wlp.info.config.layerConfigs[i].sensitivityX); + int y = + -((relativeCurrentY - app->monitors[m].info.bounds.h / 2) * + app->monitors[m].wlp.info.config.layerConfigs[i].sensitivityY); + + for (int k = -app->monitors[m].wlp.info.config.repeatY; + k <= app->monitors[m].wlp.info.config.repeatY; + k++) + { + for (int j = -app->monitors[m].wlp.info.config.repeatX; + j <= app->monitors[m].wlp.info.config.repeatX; + j++) + { + SDL_Rect dest = { + .x = x + j * app->monitors[m].info.config.wlpBounds.w, + .y = y + k * app->monitors[m].info.config.wlpBounds.h, + .w = app->monitors[m].info.config.wlpBounds.w, + .h = app->monitors[m].info.config.wlpBounds.h, + }; + + if (SDL_RenderCopy(app->renderer, app->monitors[m].wlp.layers[i].tex, &src, &dest) != 0) + { + lwpLog(LOG_ERROR, "Error rendering copy: %s", SDL_GetError()); + quit = 1; + } + } + } + } + + if (SDL_SetRenderTarget(app->renderer, app->monitors[m].tex) != 0) + { + lwpLog(LOG_ERROR, "Error setting the renderer target: %s", SDL_GetError()); + quit = 1; + } + + SDL_Rect src = { + .x = 0, + .y = 0, + .w = app->monitors[m].info.config.wlpBounds.w, + .h = app->monitors[m].info.config.wlpBounds.h, + }; + + SDL_Rect dest = { + .x = app->monitors[m].info.config.wlpBounds.x, + .y = app->monitors[m].info.config.wlpBounds.y, + .w = app->monitors[m].info.config.wlpBounds.w, + .h = app->monitors[m].info.config.wlpBounds.h, + }; + + if (SDL_RenderCopy(app->renderer, app->monitors[m].wlp.tex, &src, &dest) != 0) + { + lwpLog(LOG_ERROR, "Error rendering copy: %s", SDL_GetError()); + quit = 1; + } + + SDL_SetRenderTarget(app->renderer, NULL); + + SDL_Rect finalSrc = { + .x = 0, + .y = 0, + .w = app->monitors[m].info.bounds.w, + .h = app->monitors[m].info.bounds.h, + }; + + SDL_Rect finalDest = { + .x = app->monitors[m].info.bounds.x, + .y = app->monitors[m].info.bounds.y, + .w = app->monitors[m].info.bounds.w, + .h = app->monitors[m].info.bounds.h, + }; + + if (SDL_RenderCopy(app->renderer, app->monitors[m].tex, &finalSrc, &finalDest) != 0) + { + lwpLog(LOG_ERROR, "Error rendering copy: %s", SDL_GetError()); + quit = 1; + } + } + SDL_RenderPresent(app->renderer); + SDL_Delay(1000 / app->config.targetFps); + } +} diff --git a/src/wlp/window.c b/src/wlp/window.c new file mode 100644 index 0000000..c160103 --- /dev/null +++ b/src/wlp/window.c @@ -0,0 +1,127 @@ +#include "main.h" + +#ifdef __WIN32 +#include +#endif // __WIN32 + +#ifdef __LINUX +#include +#include +#include +#endif //__LINUX + +#ifdef __WIN32 + +static HWND iconWorkerw; +static BOOL CALLBACK getIconWorkerw(HWND hWnd, LPARAM lParam) +{ + char buff[10]; + GetClassName(hWnd, buff, 10); + + if (strcmp(buff, "WorkerW") == 0) + { + HWND defView = FindWindowEx(hWnd, NULL, "SHELLDLL_DefView", NULL); + if (defView) + { + iconWorkerw = hWnd; + return FALSE; + } + } + return TRUE; +} + +#endif + +void initWindow(App *app) +{ +#ifdef __WIN32 + + app->window = + SDL_CreateWindow("Parallax wallpaper", 0, 0, 0, 0, SDL_WINDOW_OPENGL | SDL_WINDOW_HIDDEN); + if (app->window == NULL) lwpLog(LOG_ERROR, "%s", SDL_GetError()); + + SDL_SysWMinfo sysWmInfo; + SDL_VERSION(&sysWmInfo.version) + SDL_GetWindowWMInfo(app->window, &sysWmInfo); + HWND hWindow = sysWmInfo.info.win.window; + + HWND progman = FindWindow("Progman", NULL); + iconWorkerw = progman; + SendMessageTimeout(progman, 0x052C, NULL, NULL, SMTO_NORMAL, 1000, NULL); + if (!FindWindowEx(progman, NULL, "SHELLDLL_DefView", NULL)) EnumWindows(getIconWorkerw, NULL); + + HWND wallpaperWorkerw = GetWindow(iconWorkerw, GW_HWNDNEXT); + SetParent(hWindow, wallpaperWorkerw); + SetWindowLongPtr( + hWindow, GWL_EXSTYLE, WS_EX_LEFT | WS_EX_LTRREADING | WS_EX_RIGHTSCROLLBAR | WS_EX_NOACTIVATE + ); + SetWindowLongPtr(hWindow, GWL_STYLE, WS_CHILDWINDOW | WS_VISIBLE); + + SetWindowPos( + hWindow, + NULL, + 0, + 0, + GetSystemMetrics(SM_CXVIRTUALSCREEN), + GetSystemMetrics(SM_CYVIRTUALSCREEN), + SWP_NOZORDER | SWP_NOACTIVATE | SWP_SHOWWINDOW + ); + +#else + + if (!app->config.drawOnRootWindow) + { + Display *display = XOpenDisplay(NULL); + XCloseDisplay(display); + + app->window = SDL_CreateWindow( + "Layered WallPaper", + 0, + 0, + DisplayWidth(display, 0), + DisplayHeight(display, 0), + SDL_WINDOW_OPENGL + ); + + SDL_SysWMinfo wmInfo; + SDL_GetVersion(&wmInfo.version); + SDL_GetWindowWMInfo(app->window, &wmInfo); + + Window xWnd = wmInfo.info.x11.window; + display = wmInfo.info.x11.display; + + Atom atomType = XInternAtom(display, "_NET_WM_WINDOW_TYPE", 0); + Atom atomDesktop = XInternAtom(display, "_NET_WM_WINDOW_TYPE_DESKTOP", 0); + XChangeProperty( + display, + xWnd, + atomType, + XA_ATOM, + 32, + PropModeReplace, + (const unsigned char *)&atomDesktop, + 1 + ); + + Window rootWindow = RootWindow(display, DefaultScreen(display)); + + XReparentWindow(display, xWnd, rootWindow, 0, 0); + + XSync(display, 0); + } + else + { + Display *display = XOpenDisplay(NULL); + Window rootWindow = RootWindow(display, DefaultScreen(display)); + app->window = SDL_CreateWindowFrom((void *)rootWindow); + XCloseDisplay(display); + } + +#endif + + if (app->window == NULL) lwpLog(LOG_ERROR, "Failed to initialize window: %s", SDL_GetError()); + + app->renderer = + SDL_CreateRenderer(app->window, -1, SDL_RENDERER_ACCELERATED | SDL_RENDERER_PRESENTVSYNC); + if (app->renderer == NULL) lwpLog(LOG_ERROR, "Failed to initialize renderer: %s", SDL_GetError()); +} diff --git a/uninstall.bat b/uninstall.bat deleted file mode 100644 index 794b279..0000000 --- a/uninstall.bat +++ /dev/null @@ -1,26 +0,0 @@ -@echo off -title Uninstall Layered WallPaper - -echo Are You sure, You want to remove Layered WallPaper from Your computer? -set /p val="(y/n) > " -if not %val%==y ( - exit -) - -echo Killing all running instances... -taskkill /F /IM lwp.exe -echo. - -echo Restarting explorer... -taskkill /im explorer.exe /f -start explorer.exe -echo. - -echo Removing Layered WallPaper's registry keys.. -reg delete "HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\layeredWallPaper" /f > nul -reg delete "HKEY_LOCAL_MACHINE\Software\Microsoft\Windows\CurrentVersion\Run" /v "lwp" /f > nul -echo. - -echo Removing Layered WallPaper's files... -rmdir /S /Q "%~dp0" -exit \ No newline at end of file diff --git a/wallpaper.c b/wallpaper.c deleted file mode 100644 index a57d906..0000000 --- a/wallpaper.c +++ /dev/null @@ -1,73 +0,0 @@ -#ifdef _MSC_VER -#include -#else -#include -#endif - -#include "debug.h" -#include "parser.h" - -static int loadMonitor(App *app, Monitor *monitor, Wallpaper *wallpaper, const char *dirPath) -{ - char path[PATH_MAX]; - - snprintf(path, PATH_MAX, "%s/wallpaper.cfg", dirPath); - - if (!parseWallpaperConfig(wallpaper, path)) - { - return 0; - } - - for (int i = 0; i < wallpaper->layersCount; i++) - { - snprintf(path, PATH_MAX, "%s/%d.bmp", dirPath, i + 1); - - SDL_Surface *surf = SDL_LoadBMP(path); - if (!surf) - { - lwpLog(LOG_ERROR, "File %s not found", path); - return 0; - } - - if (i == 0) - { - wallpaper->originalW = surf->w; - wallpaper->originalH = surf->h; - } - - wallpaper->layers[i].tex = SDL_CreateTextureFromSurface(app->renderer, surf); - - SDL_FreeSurface(surf); - } - - wallpaper->tex = - SDL_CreateTexture(app->renderer, SDL_PIXELFORMAT_ARGB8888, SDL_TEXTUREACCESS_TARGET, - monitor->wallpaperW, monitor->wallpaperH); - - monitor->tex = SDL_CreateTexture(app->renderer, SDL_PIXELFORMAT_ARGB8888, - SDL_TEXTUREACCESS_TARGET, monitor->w, monitor->h); - - return 1; -} - -int loadMonitors(App *app, Config *cfg) -{ - for (int m = 0; m < cfg->monitorsCount; m++) - if (!loadMonitor(app, &cfg->monitors[m], &cfg->monitors[m].wallpaper, - cfg->monitors[m].wallpaper.dirPath)) - return 0; - - return 1; -} - -void freeMonitor(Monitor *monitor) -{ - SDL_DestroyTexture(monitor->tex); - SDL_DestroyTexture(monitor->wallpaper.tex); - - for (int i = 0; i < monitor->wallpaper.layersCount; i++) - { - SDL_DestroyTexture(monitor->wallpaper.layers[i].tex); - } - free(monitor->wallpaper.layers); -} diff --git a/wallpaper.h b/wallpaper.h deleted file mode 100644 index 11da0eb..0000000 --- a/wallpaper.h +++ /dev/null @@ -1,9 +0,0 @@ -#ifndef WALLPAPER_H -#define WALLPAPER_H - -#include "main.h" - -int loadMonitors(App *app, Config *cfg); -void freeMonitor(Monitor *monitor); - -#endif diff --git a/wallpapers/default-fullhd/wallpaper.cfg b/wallpapers/default-fullhd/wallpaper.cfg index f2939f1..6276979 100644 --- a/wallpapers/default-fullhd/wallpaper.cfg +++ b/wallpapers/default-fullhd/wallpaper.cfg @@ -1,14 +1,5 @@ -# Layers count -count=4 - -# Base movement sensitivity -# Sensitivity for each layer is [ movement_x * (i-1) ], where i is the layer index. -movement_x=0.05 -movement_y=0.05 - -# You can override base sensitivity for a specific layer like this: -# movement2_x = 0.1 - -# Set this to 1, if Your wallpaper is repeatable -repeat_x=0 -repeat_y=0 +count=4; +movement_x=0.05; +movement_y=0.05; +repeat_x=0; +repeat_y=0; diff --git a/window.c b/window.c deleted file mode 100644 index 90aa3dd..0000000 --- a/window.c +++ /dev/null @@ -1,232 +0,0 @@ -#include "debug.h" -#include "main.h" - -#ifdef __WIN32 -#include -#include -#ifdef _MSC_VER -#include -#else -#include -#endif // _MSC_VER -#endif // __WIN32 - -#ifdef __LINUX -#include -#include -#include -#endif //__LINUX - -#ifdef __WIN32 - -static HWND iconWorkerw; -static BOOL CALLBACK getIconWorkerw(HWND hWnd, LPARAM lParam) -{ - char buff[10]; - GetClassName(hWnd, buff, 10); - - if (strcmp(buff, "WorkerW") == 0) - { - HWND defView = FindWindowEx(hWnd, NULL, "SHELLDLL_DefView", NULL); - if (defView) - { - iconWorkerw = hWnd; - return FALSE; - } - } - return TRUE; -} - -#define WM_TRAY_ICON (WM_USER + 1) - -static NOTIFYICONDATA nid; -static int quit = 0; - -void removeTrayIcon() { Shell_NotifyIcon(NIM_DELETE, &nid); } - -int updateTrayIcon() -{ - MSG msg; - while (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE)) - { - TranslateMessage(&msg); - DispatchMessage(&msg); - } - - return !quit; -} - -static LRESULT CALLBACK wndProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam) -{ - switch (uMsg) - { - case WM_TRAY_ICON: - if (lParam == WM_RBUTTONDOWN || lParam == WM_LBUTTONDOWN) - { - int res = MessageBox(NULL, "Do You want to run Layered WallPaper with debug console?", - "Restart Layered WallPaper", MB_YESNOCANCEL | MB_ICONQUESTION); - - TCHAR processParam = NULL; - - if (res != IDCANCEL) - { - TCHAR fileName[MAX_PATH]; - GetModuleFileName(NULL, fileName, MAX_PATH); - - TCHAR cmd[MAX_PATH + 10]; - _tcscpy(cmd, fileName); - - if (res == IDYES) _tcscat(cmd, " /console"); - - STARTUPINFO si; - memset(&si, 0, sizeof(STARTUPINFO)); - - PROCESS_INFORMATION pi; - - CreateProcess(NULL, cmd, NULL, NULL, FALSE, 0, NULL, NULL, &si, &pi); - - quit = 1; - } - } - break; - } -} - -void initTrayIcon() -{ - // Create an invisible window to process tray icon events - - HINSTANCE hInstance = GetModuleHandle(NULL); - const wchar_t CLASS_NAME[] = L"Hidden Window"; - WNDCLASS wc; - memset(&wc, 0, sizeof(WNDCLASS)); - wc.lpfnWndProc = wndProc; - wc.hInstance = hInstance; - wc.lpszClassName = CLASS_NAME; - RegisterClass(&wc); - HWND hWnd = CreateWindowEx(0, CLASS_NAME, L"", WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, CW_USEDEFAULT, - CW_USEDEFAULT, CW_USEDEFAULT, NULL, NULL, hInstance, NULL); - - // Create tray icon - - nid.cbSize = sizeof(NOTIFYICONDATA); - nid.hWnd = hWnd; - nid.uCallbackMessage = WM_TRAY_ICON; - nid.hIcon = LoadIcon(hInstance, "ID"); - nid.uFlags = NIF_ICON | NIF_MESSAGE; - - Shell_NotifyIcon(NIM_ADD, &nid); -} - -void initWindow(App *app, Config *cfg) -{ - app->window = - SDL_CreateWindow("Parallax wallpaper", 0, 0, 0, 0, SDL_WINDOW_OPENGL | SDL_WINDOW_HIDDEN); - if (app->window == NULL) lwpLog(LOG_ERROR, "%s", SDL_GetError()); - - SDL_SysWMinfo sysWmInfo; - SDL_VERSION(&sysWmInfo.version) - SDL_GetWindowWMInfo(app->window, &sysWmInfo); - HWND hWindow = sysWmInfo.info.win.window; - - HWND progman = FindWindow("Progman", NULL); - iconWorkerw = progman; - SendMessageTimeout(progman, 0x052C, NULL, NULL, SMTO_NORMAL, 1000, NULL); - if (!FindWindowEx(progman, NULL, "SHELLDLL_DefView", NULL)) EnumWindows(getIconWorkerw, NULL); - - HWND wallpaperWorkerw = GetWindow(iconWorkerw, GW_HWNDNEXT); - SetParent(hWindow, wallpaperWorkerw); - SetWindowLongPtr(hWindow, GWL_EXSTYLE, - WS_EX_LEFT | WS_EX_LTRREADING | WS_EX_RIGHTSCROLLBAR | WS_EX_NOACTIVATE); - SetWindowLongPtr(hWindow, GWL_STYLE, WS_CHILDWINDOW | WS_VISIBLE); - - SetWindowPos(hWindow, NULL, 0, 0, - GetSystemMetrics(SM_CXVIRTUALSCREEN), - GetSystemMetrics(SM_CYVIRTUALSCREEN), - SWP_NOZORDER | SWP_NOACTIVATE | SWP_SHOWWINDOW); -} - -#elif __DARWIN - -// Helper macros for objc runtime interaction -#define OBJC_MSG_INT ((id(*)(id, SEL, int))objc_msgSend) -#define OBJC_MSG_ID ((id(*)(id, SEL, id))objc_msgSend) -#define OBJC_MSG_PTR ((id(*)(id, SEL, void *))objc_msgSend) -#define OBJC_MSG_CLS ((id(*)(Class, SEL))objc_msgSend) -#define OBJC_MSG_CLS_CHR ((id(*)(Class, SEL, char *))objc_msgSend) - -void initWindow(App *app, Config *cfg) -{ - // Get main display size - const CGDirectDisplayID displayID = CGMainDisplayID(); - const size_t w = CGDisplayPixelsWide(displayID); - const size_t h = CGDisplayPixelsHigh(displayID); - const struct CGRect frameRect = {0, 0, w, h}; - - // Get shared NSApplication instance - const id ns_app = OBJC_MSG_CLS(objc_getClass("NSApplication"), sel_getUid("sharedApplication")); - OBJC_MSG_INT(ns_app, sel_getUid("setActivationPolicy:"), - 0); // NSApplicationActivationPolicyRegular - - // Create NSWindow - const id window = ((id(*)(id, SEL, struct CGRect, int, int, int))objc_msgSend)( - OBJC_MSG_CLS(objc_getClass("NSWindow"), sel_getUid("alloc")), - sel_getUid("initWithContentRect:styleMask:backing:defer:"), frameRect, - 0, // NSWindowStyleMaskBorderless - 2, // NSBackingStoreBuffered - false); - - // Set window attributes - OBJC_MSG_ID(window, sel_getUid("setTitle:"), - OBJC_MSG_CLS_CHR(objc_getClass("NSString"), sel_getUid("stringWithUTF8String:"), - "Parallax wallpaper")); - OBJC_MSG_PTR(window, sel_getUid("makeKeyAndOrderFront:"), nil); - OBJC_MSG_INT(window, sel_getUid("setLevel:"), kCGDesktopWindowLevel - 1); - OBJC_MSG_INT(ns_app, sel_getUid("activateIgnoringOtherApps:"), true); - - // Create SDL window from NSWindow - app->window = SDL_CreateWindowFrom((void *)window); - if (app->window == NULL) lwpLog(LOG_ERROR, "%s", SDL_GetError()); -} - -#elif __LINUX - -void initWindow(App *app, Config *cfg) -{ - if (cfg->reloadRootWnd) - { - Display *display = XOpenDisplay(NULL); - XCloseDisplay(display); - - app->window = SDL_CreateWindow("Parallax wallpaper", 0, 0, DisplayWidth(display, 0), - DisplayHeight(display, 0), SDL_WINDOW_OPENGL); - - SDL_SysWMinfo wmInfo; - SDL_GetVersion(&wmInfo.version); - SDL_GetWindowWMInfo(app->window, &wmInfo); - - Window xWnd = wmInfo.info.x11.window; - display = wmInfo.info.x11.display; - - Atom atomType = XInternAtom(display, "_NET_WM_WINDOW_TYPE", 0); - Atom atomDesktop = XInternAtom(display, "_NET_WM_WINDOW_TYPE_DESKTOP", 0); - XChangeProperty(display, xWnd, atomType, XA_ATOM, 32, PropModeReplace, - (const unsigned char *)&atomDesktop, 1); - - Window rootWindow = RootWindow(display, DefaultScreen(display)); - - XReparentWindow(display, xWnd, rootWindow, 0, 0); - - XSync(display, 0); - } - else - { - Display *display = XOpenDisplay(NULL); - Window rootWindow = RootWindow(display, DefaultScreen(display)); - app->window = SDL_CreateWindowFrom((void *)rootWindow); - XCloseDisplay(display); - } - - if (app->window == NULL) lwpLog(LOG_ERROR, "%s", SDL_GetError()); -} -#endif diff --git a/window.h b/window.h deleted file mode 100644 index b69063f..0000000 --- a/window.h +++ /dev/null @@ -1,15 +0,0 @@ -#ifndef WINDOW_H -#define WINDOW_H - -#include "main.h" -#include "parser.h" - -void initWindow(App *app, Config *cfg); - -#ifdef __WIN32 -void initTrayIcon(); -int updateTrayIcon(); -void removeTrayIcon(); -#endif - -#endif