From 3cbc90bf94783bfc6f107fba86baee2027d0bd89 Mon Sep 17 00:00:00 2001 From: Vaxry Date: Wed, 17 Jul 2024 16:25:07 +0200 Subject: [PATCH] core: migrate to hyprwayland-scanner Additionally: - format - yeet clang-tidy - fixup clang-format --- .clang-format | 117 ++++++-------------- .clang-tidy | 6 - .gitignore | 5 + CMakeLists.txt | 75 +++++++------ README.md | 11 +- src/Hyprpaper.cpp | 196 ++++++++++++++++++++------------- src/Hyprpaper.hpp | 90 ++++++++------- src/config/ConfigManager.cpp | 43 ++++---- src/config/ConfigManager.hpp | 12 +- src/debug/Log.cpp | 29 ++--- src/debug/Log.hpp | 2 +- src/defines.hpp | 11 +- src/events/Events.cpp | 164 --------------------------- src/events/Events.hpp | 51 --------- src/helpers/Bmp.cpp | 53 ++++----- src/helpers/Jpeg.cpp | 13 ++- src/helpers/MiscFunctions.hpp | 6 +- src/helpers/Monitor.cpp | 24 ++++ src/helpers/Monitor.hpp | 33 +++--- src/helpers/PoolBuffer.hpp | 15 +-- src/helpers/Vector2D.cpp | 23 ---- src/helpers/Vector2D.hpp | 39 ------- src/helpers/Webp.cpp | 25 ++--- src/includes.hpp | 24 +--- src/ipc/Socket.cpp | 31 +++--- src/ipc/Socket.hpp | 16 ++- src/main.cpp | 14 +-- src/render/LayerSurface.cpp | 88 ++++++++++----- src/render/LayerSurface.hpp | 23 ++-- src/render/WallpaperTarget.cpp | 19 ++-- src/render/WallpaperTarget.hpp | 11 +- 31 files changed, 518 insertions(+), 751 deletions(-) delete mode 100644 .clang-tidy delete mode 100644 src/events/Events.cpp delete mode 100644 src/events/Events.hpp create mode 100644 src/helpers/Monitor.cpp delete mode 100644 src/helpers/Vector2D.cpp delete mode 100644 src/helpers/Vector2D.hpp diff --git a/.clang-format b/.clang-format index 7c7590a..90314ef 100644 --- a/.clang-format +++ b/.clang-format @@ -1,114 +1,65 @@ --- Language: Cpp -Standard: Auto -AccessModifierOffset: -4 -AlignAfterOpenBracket: DontAlign -AlignArrayOfStructures: None -AlignConsecutiveAssignments: None -AlignConsecutiveBitFields: Consecutive -AlignConsecutiveDeclarations: None -AlignConsecutiveMacros: None +BasedOnStyle: LLVM + +AccessModifierOffset: -2 +AlignAfterOpenBracket: Align +AlignConsecutiveMacros: true +AlignConsecutiveAssignments: true AlignEscapedNewlines: Right -AlignOperands: DontAlign +AlignOperands: false AlignTrailingComments: true -AllowAllArgumentsOnNextLine: false +AllowAllArgumentsOnNextLine: true AllowAllConstructorInitializersOnNextLine: true -AllowAllParametersOfDeclarationOnNextLine: false -AllowShortBlocksOnASingleLine: Empty -AllowShortCaseLabelsOnASingleLine: false -AllowShortEnumsOnASingleLine: true -AllowShortFunctionsOnASingleLine: All +AllowAllParametersOfDeclarationOnNextLine: true +AllowShortBlocksOnASingleLine: true +AllowShortCaseLabelsOnASingleLine: true +AllowShortFunctionsOnASingleLine: Empty AllowShortIfStatementsOnASingleLine: Never AllowShortLambdasOnASingleLine: All AllowShortLoopsOnASingleLine: false AlwaysBreakAfterDefinitionReturnType: None AlwaysBreakAfterReturnType: None AlwaysBreakBeforeMultilineStrings: false -AlwaysBreakTemplateDeclarations: MultiLine -BinPackArguments: true -BinPackParameters: true -BitFieldColonSpacing: Both -BreakAfterJavaFieldAnnotations: true -BreakBeforeBinaryOperators: NonAssignment -BreakBeforeConceptDeclarations: true -BreakBeforeInheritanceComma: false -BreakBeforeTernaryOperators: true -BreakConstructorInitializers: BeforeComma -BreakConstructorInitializersBeforeComma: false -BreakInheritanceList: BeforeColon -BreakStringLiterals: true -ColumnLimit: 0 -CompactNamespaces: true +AlwaysBreakTemplateDeclarations: Yes +BreakBeforeBraces: Attach +BreakBeforeTernaryOperators: false +BreakConstructorInitializers: AfterColon +ColumnLimit: 180 +CompactNamespaces: false ConstructorInitializerAllOnOneLineOrOnePerLine: false -ConstructorInitializerIndentWidth: 8 -ContinuationIndentWidth: 4 -DeriveLineEnding: true -DerivePointerAlignment: false -DisableFormat: false -EmptyLineAfterAccessModifier: Never -EmptyLineBeforeAccessModifier: LogicalBlock +ExperimentalAutoDetectBinPacking: false FixNamespaceComments: false IncludeBlocks: Preserve -IncludeIsMainRegex: (Test)?$ -IncludeIsMainSourceRegex: '' -IndentAccessModifiers: false -IndentCaseBlocks: false IndentCaseLabels: true -IndentExternBlock: AfterExternBlock -IndentGotoLabels: true -IndentPPDirectives: None IndentWidth: 4 -IndentWrappedFunctionNames: false -InsertTrailingCommas: None -JavaScriptQuotes: Leave -JavaScriptWrapImports: true -KeepEmptyLinesAtTheStartOfBlocks: true -LambdaBodyIndentation: Signature -MaxEmptyLinesToKeep: 1 -NamespaceIndentation: All -PPIndentWidth: -1 -PackConstructorInitializers: BinPack -PenaltyBreakAssignment: 2 -PenaltyBreakBeforeFirstCallParameter: 19 -PenaltyBreakComment: 300 -PenaltyBreakFirstLessLess: 120 -PenaltyBreakOpenParenthesis: 0 -PenaltyBreakString: 1000 -PenaltyBreakTemplateDeclaration: 10 -PenaltyExcessCharacter: 1000000 -PenaltyIndentedWhitespace: 0 -PenaltyReturnTypeOnItsOwnLine: 60 PointerAlignment: Left -QualifierAlignment: Leave -ReferenceAlignment: Pointer -ReflowComments: true -RemoveBracesLLVM: false -SeparateDefinitionBlocks: Leave -ShortNamespaceLines: 1 -SortIncludes: CaseSensitive -SortJavaStaticImport: Before -SortUsingDeclarations: true +ReflowComments: false +SortIncludes: false +SortUsingDeclarations: false SpaceAfterCStyleCast: false SpaceAfterLogicalNot: false SpaceAfterTemplateKeyword: true -SpaceAroundPointerQualifiers: Default -SpaceBeforeAssignmentOperators: true -SpaceBeforeCaseColon: false SpaceBeforeCtorInitializerColon: true SpaceBeforeInheritanceColon: true SpaceBeforeParens: ControlStatements SpaceBeforeRangeBasedForLoopColon: true -SpaceBeforeSquareBrackets: false -SpaceInEmptyBlock: true SpaceInEmptyParentheses: false SpacesBeforeTrailingComments: 1 -SpacesInAngles: Never +SpacesInAngles: false SpacesInCStyleCastParentheses: false -SpacesInConditionalStatement: false -SpacesInContainerLiterals: true +SpacesInContainerLiterals: false SpacesInParentheses: false SpacesInSquareBrackets: false +Standard: Auto TabWidth: 4 -UseCRLF: false UseTab: Never -... + +AllowShortEnumsOnASingleLine: false + +BraceWrapping: + AfterEnum: false + +AlignConsecutiveDeclarations: AcrossEmptyLines + +NamespaceIndentation: All diff --git a/.clang-tidy b/.clang-tidy deleted file mode 100644 index cddc8f8..0000000 --- a/.clang-tidy +++ /dev/null @@ -1,6 +0,0 @@ ---- -Checks: '-*,clang-diagnostic-*,bugprone-*,cert-*,misc-*,modernize-*,performance-*,readability-*,hicpp-exception-baseclass,hicpp-avoid-goto,-clang-diagnostic-address-of-packed-member,-cert-dcl16-c,-cert-dcl21-cpp,-cert-err58-cpp,-misc-unused-parameters,-misc-non-private-member-variables-in-classes,-modernize-avoid-c-arrays,-modernize-concat-nested-namespaces,-modernize-raw-string-literal,-modernize-use-default-member-init,-modernize-use-nodiscard,-modernize-use-override,-modernize-use-trailing-return-type,-readability-else-after-return,-readability-identifier-naming,-readability-implicit-bool-cast,-readability-implicit-bool-conversion,-readability-magic-numbers,-readability-named-parameter,-readability-qualified-auto,-readability-redundant-access-specifiers,-readability-redundant-member-init,-readability-uppercase-literal-suffix' -WarningsAsErrors: '*' -HeaderFilterRegex: '' -FormatStyle: none -... diff --git a/.gitignore b/.gitignore index deae30f..8d38ed4 100644 --- a/.gitignore +++ b/.gitignore @@ -19,6 +19,11 @@ result *-protocol.h .ccls-cache +protocols/*.hpp +protocols/*.cpp + +.cache/ + hyprctl/hyprctl gmon.out diff --git a/CMakeLists.txt b/CMakeLists.txt index b8746fe..225098a 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,4 +1,4 @@ -cmake_minimum_required(VERSION 3.4) +cmake_minimum_required(VERSION 3.12) project(hyprpaper DESCRIPTION "A blazing fast wayland wallpaper utility" VERSION 0.7.0 @@ -36,35 +36,6 @@ execute_process( # # -find_program(WaylandScanner NAMES wayland-scanner) -message(STATUS "Found WaylandScanner at ${WaylandScanner}") -execute_process( - COMMAND pkg-config --variable=pkgdatadir wayland-protocols - WORKING_DIRECTORY ${CMAKE_SOURCE_DIR} - OUTPUT_VARIABLE WAYLAND_PROTOCOLS_DIR - OUTPUT_STRIP_TRAILING_WHITESPACE) -message(STATUS "Found wayland-protocols at ${WAYLAND_PROTOCOLS_DIR}") - -function(protocol protoPath protoName external) - if (external) - execute_process( - COMMAND ${WaylandScanner} client-header ${protoPath} ${protoName}-protocol.h - WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}) - execute_process( - COMMAND ${WaylandScanner} private-code ${protoPath} ${protoName}-protocol.c - WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}) - target_sources(hyprpaper PRIVATE ${protoName}-protocol.h ${protoName}-protocol.c) - else() - execute_process( - COMMAND ${WaylandScanner} client-header ${WAYLAND_PROTOCOLS_DIR}/${protoPath} ${protoName}-protocol.h - WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}) - execute_process( - COMMAND ${WaylandScanner} private-code ${WAYLAND_PROTOCOLS_DIR}/${protoPath} ${protoName}-protocol.c - WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}) - target_sources(hyprpaper PRIVATE ${protoName}-protocol.h ${protoName}-protocol.c) - endif() -endfunction() - include_directories(.) set(CMAKE_CXX_STANDARD 23) add_compile_options(-DWLR_USE_UNSTABLE) @@ -72,16 +43,50 @@ add_compile_options(-Wall -Wextra -Wno-unused-parameter -Wno-unused-value -Wno-m find_package(Threads REQUIRED) find_package(PkgConfig REQUIRED) -pkg_check_modules(deps REQUIRED IMPORTED_TARGET wayland-client wayland-protocols cairo pango pangocairo libjpeg libwebp hyprlang>=0.2.0 hyprutils>=0.2.0) +pkg_check_modules(deps REQUIRED IMPORTED_TARGET wayland-client wayland-protocols cairo pango pangocairo libjpeg libwebp hyprlang>=0.2.0 hyprutils>=0.2.0 hyprwayland-scanner>=0.4.0) file(GLOB_RECURSE SRCFILES "src/*.cpp") add_executable(hyprpaper ${SRCFILES}) -protocol("protocols/wlr-layer-shell-unstable-v1.xml" "wlr-layer-shell-unstable-v1" true) -protocol("stable/xdg-shell/xdg-shell.xml" "xdg-shell" false) -protocol("stable/viewporter/viewporter.xml" "viewporter" false) -protocol("staging/fractional-scale/fractional-scale-v1.xml" "fractional-scale-v1" false) +pkg_get_variable(WAYLAND_PROTOCOLS_DIR wayland-protocols pkgdatadir) +message(STATUS "Found wayland-protocols at ${WAYLAND_PROTOCOLS_DIR}") +pkg_get_variable(WAYLAND_CLIENT_DIR wayland-client pkgdatadir) +message(STATUS "Found wayland-client at ${WAYLAND_CLIENT_DIR}") + +function(protocolNew protoPath protoName external) + if (external) + set(path ${CMAKE_SOURCE_DIR}/${protoPath}) + else() + set(path ${WAYLAND_PROTOCOLS_DIR}/${protoPath}) + endif() + add_custom_command( + OUTPUT ${CMAKE_SOURCE_DIR}/protocols/${protoName}.cpp + ${CMAKE_SOURCE_DIR}/protocols/${protoName}.hpp + COMMAND hyprwayland-scanner --client ${path}/${protoName}.xml ${CMAKE_SOURCE_DIR}/protocols/ + WORKING_DIRECTORY ${CMAKE_SOURCE_DIR} + ) + target_sources(hyprpaper PRIVATE protocols/${protoName}.cpp protocols/${protoName}.hpp) +endfunction() +function(protocolWayland) + add_custom_command( + OUTPUT ${CMAKE_SOURCE_DIR}/protocols/wayland.cpp + ${CMAKE_SOURCE_DIR}/protocols/wayland.hpp + COMMAND hyprwayland-scanner --wayland-enums --client ${WAYLAND_CLIENT_DIR}/wayland.xml ${CMAKE_SOURCE_DIR}/protocols/ + WORKING_DIRECTORY ${CMAKE_SOURCE_DIR} + ) + target_sources(hyprpaper PRIVATE protocols/wayland.cpp protocols/wayland.hpp) +endfunction() + +protocolWayland() + +protocolNew("protocols" "wlr-layer-shell-unstable-v1" true) +protocolNew("stable/linux-dmabuf" "linux-dmabuf-v1" false) +protocolNew("staging/fractional-scale" "fractional-scale-v1" false) +protocolNew("stable/viewporter" "viewporter" false) +protocolNew("stable/xdg-shell" "xdg-shell" false) +protocolNew("staging/cursor-shape" "cursor-shape-v1" false) +protocolNew("stable/tablet" "tablet-v2" false) target_compile_definitions(hyprpaper PRIVATE "-DGIT_COMMIT_HASH=\"${GIT_COMMIT_HASH}\"") target_compile_definitions(hyprpaper PRIVATE "-DGIT_BRANCH=\"${GIT_BRANCH}\"") diff --git a/README.md b/README.md index 4a97506..1c6fec6 100644 --- a/README.md +++ b/README.md @@ -30,23 +30,22 @@ The development files of these packages need to be installed on the system for ` - libjpeg-turbo - libwebp - hyprlang - -Please note hyprpaper > 0.5.0 depends on [hyprlang](https://github.com/hyprwm/hyprlang) which is new -and might not be packaged for your distro yet. If that's the case, build and install it from source. +- hyprutils +- hyprwayland-scanner To install all of these in Fedora, run this command: ``` -sudo dnf install wayland-devel wayland-protocols-devel hyprlang-devel pango-devel cairo-devel file-devel libglvnd-devel libglvnd-core-devel libjpeg-turbo-devel libwebp-devel gcc-c++ +sudo dnf install wayland-devel wayland-protocols-devel hyprlang-devel pango-devel cairo-devel file-devel libglvnd-devel libglvnd-core-devel libjpeg-turbo-devel libwebp-devel gcc-c++ hyprutils-devel hyprwayland-scanner ``` On Arch: ``` -sudo pacman -S ninja gcc wayland-protocols libjpeg-turbo libwebp pango cairo pkgconf cmake libglvnd wayland +sudo pacman -S ninja gcc wayland-protocols libjpeg-turbo libwebp pango cairo pkgconf cmake libglvnd wayland hyprutils hyprwayland-scanner hyprlang ``` On OpenSUSE: ``` -sudo zypper install ninja gcc-c++ wayland-protocols-devel Mesa-libGLESv3-devel file-devel +sudo zypper install ninja gcc-c++ wayland-protocols-devel Mesa-libGLESv3-devel file-devel hyprutils-devel hyprwayland-scanner ``` ### Building diff --git a/src/Hyprpaper.cpp b/src/Hyprpaper.cpp index 026ff34..ca9d1ae 100644 --- a/src/Hyprpaper.cpp +++ b/src/Hyprpaper.cpp @@ -6,6 +6,47 @@ CHyprpaper::CHyprpaper() = default; +static void handleGlobal(CCWlRegistry* registry, uint32_t name, const char* interface, uint32_t version) { + if (strcmp(interface, wl_compositor_interface.name) == 0) { + g_pHyprpaper->m_pCompositor = makeShared((wl_proxy*)wl_registry_bind((wl_registry*)registry->resource(), name, &wl_compositor_interface, 4)); + } else if (strcmp(interface, wl_shm_interface.name) == 0) { + g_pHyprpaper->m_pSHM = makeShared((wl_proxy*)wl_registry_bind((wl_registry*)registry->resource(), name, &wl_shm_interface, 1)); + } else if (strcmp(interface, wl_output_interface.name) == 0) { + g_pHyprpaper->m_mtTickMutex.lock(); + + const auto PMONITOR = g_pHyprpaper->m_vMonitors.emplace_back(std::make_unique()).get(); + PMONITOR->wayland_name = name; + PMONITOR->name = ""; + PMONITOR->output = makeShared((wl_proxy*)wl_registry_bind((wl_registry*)registry->resource(), name, &wl_output_interface, 4)); + PMONITOR->registerListeners(); + + g_pHyprpaper->m_mtTickMutex.unlock(); + } else if (strcmp(interface, wl_seat_interface.name) == 0) { + g_pHyprpaper->createSeat(makeShared((wl_proxy*)wl_registry_bind((wl_registry*)registry->resource(), name, &wl_seat_interface, 1))); + } else if (strcmp(interface, zwlr_layer_shell_v1_interface.name) == 0) { + g_pHyprpaper->m_pLayerShell = makeShared((wl_proxy*)wl_registry_bind((wl_registry*)registry->resource(), name, &zwlr_layer_shell_v1_interface, 1)); + } else if (strcmp(interface, wp_fractional_scale_manager_v1_interface.name) == 0 && !g_pHyprpaper->m_bNoFractionalScale) { + g_pHyprpaper->m_pFractionalScale = + makeShared((wl_proxy*)wl_registry_bind((wl_registry*)registry->resource(), name, &wp_fractional_scale_manager_v1_interface, 1)); + } else if (strcmp(interface, wp_viewporter_interface.name) == 0) { + g_pHyprpaper->m_pViewporter = makeShared((wl_proxy*)wl_registry_bind((wl_registry*)registry->resource(), name, &wp_viewporter_interface, 1)); + } else if (strcmp(interface, wp_cursor_shape_manager_v1_interface.name) == 0) { + g_pHyprpaper->m_pCursorShape = + makeShared((wl_proxy*)wl_registry_bind((wl_registry*)registry->resource(), name, &wp_cursor_shape_manager_v1_interface, 1)); + } +} + +static void handleGlobalRemove(CCWlRegistry* registry, uint32_t name) { + for (auto& m : g_pHyprpaper->m_vMonitors) { + if (m->wayland_name == name) { + Debug::log(LOG, "Destroying output %s", m->name.c_str()); + g_pHyprpaper->clearWallpaperFromMonitor(m->name); + std::erase_if(g_pHyprpaper->m_vMonitors, [&](const auto& other) { return other->wayland_name == name; }); + return; + } + } +} + void CHyprpaper::init() { if (!lockSingleInstance()) { @@ -23,8 +64,9 @@ void CHyprpaper::init() { } // run - wl_registry* registry = wl_display_get_registry(m_sDisplay); - wl_registry_add_listener(registry, &Events::registryListener, nullptr); + auto REGISTRY = makeShared((wl_proxy*)wl_display_get_registry(m_sDisplay)); + REGISTRY->setGlobal(::handleGlobal); + REGISTRY->setGlobalRemove(::handleGlobalRemove); wl_display_roundtrip(m_sDisplay); @@ -33,7 +75,7 @@ void CHyprpaper::init() { } g_pConfigManager = std::make_unique(); - g_pIPCSocket = std::make_unique(); + g_pIPCSocket = std::make_unique(); g_pConfigManager->parse(); @@ -130,9 +172,9 @@ void CHyprpaper::preloadAllWallpapersFromConfig() { m_mWallpaperTargets[wp] = CWallpaperTarget(); if (std::filesystem::is_symlink(wp)) { - auto real_wp = std::filesystem::read_symlink(wp); + auto real_wp = std::filesystem::read_symlink(wp); std::filesystem::path absolute_path = std::filesystem::path(wp).parent_path() / real_wp; - absolute_path = absolute_path.lexically_normal(); + absolute_path = absolute_path.lexically_normal(); m_mWallpaperTargets[wp].create(absolute_path); } else { m_mWallpaperTargets[wp].create(wp); @@ -148,8 +190,28 @@ void CHyprpaper::recheckAllMonitors() { } } -void CHyprpaper::createSeat(wl_seat* pSeat) { - wl_seat_add_listener(pSeat, &Events::seatListener, pSeat); +void CHyprpaper::createSeat(SP pSeat) { + m_pSeat = pSeat; + + pSeat->setCapabilities([this](CCWlSeat* r, wl_seat_capability caps) { + if (caps & WL_SEAT_CAPABILITY_POINTER) { + m_pSeatPointer = makeShared(m_pSeat->sendGetPointer()); + if (!m_pCursorShape) + Debug::log(WARN, "No cursor-shape-v1 support from the compositor: cursor will be blank"); + else + m_pSeatCursorShapeDevice = makeShared(m_pCursorShape->sendGetPointer(m_pSeatPointer->resource())); + + m_pSeatPointer->setEnter([this](CCWlPointer* r, uint32_t serial, wl_resource* surface, wl_fixed_t x, wl_fixed_t y) { + if (!m_pCursorShape) { + m_pSeatPointer->sendSetCursor(serial, nullptr, 0, 0); + return; + } + + m_pSeatCursorShapeDevice->sendSetShape(serial, wpCursorShapeDeviceV1Shape::WP_CURSOR_SHAPE_DEVICE_V1_SHAPE_DEFAULT); + }); + } else + Debug::log(LOG, "No pointer capability from the compositor"); + }); } void CHyprpaper::recheckMonitor(SMonitor* pMonitor) { @@ -157,24 +219,7 @@ void CHyprpaper::recheckMonitor(SMonitor* pMonitor) { if (pMonitor->wantsACK) { pMonitor->wantsACK = false; - zwlr_layer_surface_v1_ack_configure(pMonitor->pCurrentLayerSurface->pLayerSurface, pMonitor->configureSerial); - - if (!pMonitor->pCurrentLayerSurface->pCursorImg) { - int XCURSOR_SIZE = 24; - if (const auto CURSORSIZENV = getenv("XCURSOR_SIZE"); CURSORSIZENV) { - try { - if (XCURSOR_SIZE = std::stoi(CURSORSIZENV); XCURSOR_SIZE <= 0) { - throw std::exception(); - } - } catch (...) { - Debug::log(WARN, "XCURSOR_SIZE environment variable is set incorrectly"); - XCURSOR_SIZE = 24; - } - } - - pMonitor->pCurrentLayerSurface->pCursorTheme = wl_cursor_theme_load(getenv("XCURSOR_THEME"), XCURSOR_SIZE * pMonitor->scale, m_sSHM); - pMonitor->pCurrentLayerSurface->pCursorImg = wl_cursor_theme_get_cursor(pMonitor->pCurrentLayerSurface->pCursorTheme, "left_ptr")->images[0]; - } + pMonitor->pCurrentLayerSurface->pLayerSurface->sendAckConfigure(pMonitor->configureSerial); } if (pMonitor->wantsReload) { @@ -184,7 +229,7 @@ void CHyprpaper::recheckMonitor(SMonitor* pMonitor) { } void CHyprpaper::removeOldHyprpaperImages() { - int cleaned = 0; + int cleaned = 0; uint64_t memoryFreed = 0; for (const auto& entry : std::filesystem::directory_iterator(std::string(getenv("XDG_RUNTIME_DIR")))) { @@ -209,11 +254,11 @@ void CHyprpaper::removeOldHyprpaperImages() { } SMonitor* CHyprpaper::getMonitorFromName(const std::string& monname) { - bool useDesc = false; - std::string desc = ""; + bool useDesc = false; + std::string desc = ""; if (monname.find("desc:") == 0) { useDesc = true; - desc = monname.substr(5); + desc = monname.substr(5); } for (auto& m : m_vMonitors) { @@ -285,10 +330,10 @@ void CHyprpaper::clearWallpaperFromMonitor(const std::string& monname) { PMONITOR->pCurrentLayerSurface = nullptr; - PMONITOR->wantsACK = false; + PMONITOR->wantsACK = false; PMONITOR->wantsReload = false; PMONITOR->initialized = false; - PMONITOR->readyForLS = true; + PMONITOR->readyForLS = true; } } @@ -300,7 +345,7 @@ void CHyprpaper::ensureMonitorHasActiveWallpaper(SMonitor* pMonitor) { if (it == m_mMonitorActiveWallpaperTargets.end()) { m_mMonitorActiveWallpaperTargets[pMonitor] = nullptr; - it = m_mMonitorActiveWallpaperTargets.find(pMonitor); + it = m_mMonitorActiveWallpaperTargets.find(pMonitor); } if (it->second) @@ -411,10 +456,10 @@ int CHyprpaper::createPoolFile(size_t size, std::string& name) { void CHyprpaper::createBuffer(SPoolBuffer* pBuffer, int32_t w, int32_t h, uint32_t format) { const size_t STRIDE = w * 4; - const size_t SIZE = STRIDE * h; + const size_t SIZE = STRIDE * h; - std::string name; - const auto FD = createPoolFile(SIZE, name); + std::string name; + const auto FD = createPoolFile(SIZE, name); if (FD == -1) { Debug::log(CRIT, "Unable to create pool file!"); @@ -422,22 +467,22 @@ void CHyprpaper::createBuffer(SPoolBuffer* pBuffer, int32_t w, int32_t h, uint32 } const auto DATA = mmap(nullptr, SIZE, PROT_READ | PROT_WRITE, MAP_SHARED, FD, 0); - const auto POOL = wl_shm_create_pool(g_pHyprpaper->m_sSHM, FD, SIZE); - pBuffer->buffer = wl_shm_pool_create_buffer(POOL, 0, w, h, STRIDE, format); - wl_shm_pool_destroy(POOL); + auto POOL = makeShared(g_pHyprpaper->m_pSHM->sendCreatePool(FD, SIZE)); + pBuffer->buffer = makeShared(POOL->sendCreateBuffer(0, w, h, STRIDE, format)); + POOL.reset(); close(FD); - pBuffer->size = SIZE; - pBuffer->data = DATA; - pBuffer->surface = cairo_image_surface_create_for_data((unsigned char*)DATA, CAIRO_FORMAT_ARGB32, w, h, STRIDE); - pBuffer->cairo = cairo_create(pBuffer->surface); + pBuffer->size = SIZE; + pBuffer->data = DATA; + pBuffer->surface = cairo_image_surface_create_for_data((unsigned char*)DATA, CAIRO_FORMAT_ARGB32, w, h, STRIDE); + pBuffer->cairo = cairo_create(pBuffer->surface); pBuffer->pixelSize = Vector2D(w, h); - pBuffer->name = name; + pBuffer->name = name; } void CHyprpaper::destroyBuffer(SPoolBuffer* pBuffer) { - wl_buffer_destroy(pBuffer->buffer); + pBuffer->buffer.reset(); cairo_destroy(pBuffer->cairo); cairo_surface_destroy(pBuffer->surface); munmap(pBuffer->data, pBuffer->size); @@ -447,7 +492,10 @@ void CHyprpaper::destroyBuffer(SPoolBuffer* pBuffer) { SPoolBuffer* CHyprpaper::getPoolBuffer(SMonitor* pMonitor, CWallpaperTarget* pWallpaperTarget) { const auto IT = std::find_if(m_vBuffers.begin(), m_vBuffers.end(), [&](const std::unique_ptr& el) { - auto scale = std::round((pMonitor->pCurrentLayerSurface && pMonitor->pCurrentLayerSurface->pFractionalScaleInfo ? pMonitor->pCurrentLayerSurface->fScale : pMonitor->scale) * 120.0) / 120.0; + auto scale = + std::round((pMonitor->pCurrentLayerSurface && pMonitor->pCurrentLayerSurface->pFractionalScaleInfo ? pMonitor->pCurrentLayerSurface->fScale : pMonitor->scale) * + 120.0) / + 120.0; return el->target == pWallpaperTarget->m_szPath && vectorDeltaLessThan(el->pixelSize, pMonitor->size * scale, 1); }); @@ -464,7 +512,7 @@ void CHyprpaper::renderWallpaperForMonitor(SMonitor* pMonitor) { recheckMonitor(pMonitor); const auto PWALLPAPERTARGET = m_mMonitorActiveWallpaperTargets[pMonitor]; - const auto CONTAIN = m_mMonitorWallpaperRenderData[pMonitor->name].contain; + const auto CONTAIN = m_mMonitorWallpaperRenderData[pMonitor->name].contain; if (!PWALLPAPERTARGET) { Debug::log(CRIT, "wallpaper target null in render??"); @@ -485,10 +533,10 @@ void CHyprpaper::renderWallpaperForMonitor(SMonitor* pMonitor) { } } - const double SURFACESCALE = pMonitor->pCurrentLayerSurface && pMonitor->pCurrentLayerSurface->pFractionalScaleInfo ? pMonitor->pCurrentLayerSurface->fScale : pMonitor->scale; - const Vector2D DIMENSIONS = Vector2D{std::round(pMonitor->size.x * SURFACESCALE), std::round(pMonitor->size.y * SURFACESCALE)}; + const double SURFACESCALE = pMonitor->pCurrentLayerSurface && pMonitor->pCurrentLayerSurface->pFractionalScaleInfo ? pMonitor->pCurrentLayerSurface->fScale : pMonitor->scale; + const Vector2D DIMENSIONS = Vector2D{std::round(pMonitor->size.x * SURFACESCALE), std::round(pMonitor->size.y * SURFACESCALE)}; - const auto PCAIRO = PBUFFER->cairo; + const auto PCAIRO = PBUFFER->cairo; cairo_save(PCAIRO); cairo_set_operator(PCAIRO, CAIRO_OPERATOR_CLEAR); cairo_paint(PCAIRO); @@ -502,19 +550,20 @@ void CHyprpaper::renderWallpaperForMonitor(SMonitor* pMonitor) { // get scale // we always do cover - double scale; - Vector2D origin; + double scale; + Vector2D origin; const bool LOWASPECTRATIO = pMonitor->size.x / pMonitor->size.y > PWALLPAPERTARGET->m_vSize.x / PWALLPAPERTARGET->m_vSize.y; if ((CONTAIN && !LOWASPECTRATIO) || (!CONTAIN && LOWASPECTRATIO)) { - scale = DIMENSIONS.x / PWALLPAPERTARGET->m_vSize.x; + scale = DIMENSIONS.x / PWALLPAPERTARGET->m_vSize.x; origin.y = -(PWALLPAPERTARGET->m_vSize.y * scale - DIMENSIONS.y) / 2.0 / scale; } else { - scale = DIMENSIONS.y / PWALLPAPERTARGET->m_vSize.y; + scale = DIMENSIONS.y / PWALLPAPERTARGET->m_vSize.y; origin.x = -(PWALLPAPERTARGET->m_vSize.x * scale - DIMENSIONS.x) / 2.0 / scale; } - Debug::log(LOG, "Image data for %s: %s at [%.2f, %.2f], scale: %.2f (original image size: [%i, %i])", pMonitor->name.c_str(), PWALLPAPERTARGET->m_szPath.c_str(), origin.x, origin.y, scale, (int)PWALLPAPERTARGET->m_vSize.x, (int)PWALLPAPERTARGET->m_vSize.y); + Debug::log(LOG, "Image data for %s: %s at [%.2f, %.2f], scale: %.2f (original image size: [%i, %i])", pMonitor->name.c_str(), PWALLPAPERTARGET->m_szPath.c_str(), origin.x, + origin.y, scale, (int)PWALLPAPERTARGET->m_vSize.x, (int)PWALLPAPERTARGET->m_vSize.y); cairo_scale(PCAIRO, scale, scale); cairo_set_source_surface(PCAIRO, PWALLPAPERTARGET->m_pCairoSurface, origin.x, origin.y); @@ -533,17 +582,19 @@ void CHyprpaper::renderWallpaperForMonitor(SMonitor* pMonitor) { cairo_set_font_size(PCAIRO, FONTSIZE); static auto* const PSPLASHCOLOR = reinterpret_cast(g_pConfigManager->config->getConfigValuePtr("splash_color")->getDataStaticPtr()); - + Debug::log(LOG, "Splash color: %x", **PSPLASHCOLOR); - cairo_set_source_rgba(PCAIRO, ((**PSPLASHCOLOR >> 16) & 0xFF) / 255.0, ((**PSPLASHCOLOR >> 8) & 0xFF) / 255.0, (**PSPLASHCOLOR & 0xFF) / 255.0, ((**PSPLASHCOLOR >> 24) & 0xFF) / 255.0); + cairo_set_source_rgba(PCAIRO, ((**PSPLASHCOLOR >> 16) & 0xFF) / 255.0, ((**PSPLASHCOLOR >> 8) & 0xFF) / 255.0, (**PSPLASHCOLOR & 0xFF) / 255.0, + ((**PSPLASHCOLOR >> 24) & 0xFF) / 255.0); cairo_text_extents_t textExtents; cairo_text_extents(PCAIRO, SPLASH.c_str(), &textExtents); cairo_move_to(PCAIRO, ((DIMENSIONS.x - textExtents.width * scale) / 2.0) / scale, ((DIMENSIONS.y * (100 - **PSPLASHOFFSET)) / 100 - textExtents.height * scale) / scale); - Debug::log(LOG, "Splash font size: %d, pos: %.2f, %.2f", FONTSIZE, (DIMENSIONS.x - textExtents.width) / 2.0 / scale, ((DIMENSIONS.y * (100 - **PSPLASHOFFSET)) / 100 - textExtents.height * scale) / scale); + Debug::log(LOG, "Splash font size: %d, pos: %.2f, %.2f", FONTSIZE, (DIMENSIONS.x - textExtents.width) / 2.0 / scale, + ((DIMENSIONS.y * (100 - **PSPLASHOFFSET)) / 100 - textExtents.height * scale) / scale); cairo_show_text(PCAIRO, SPLASH.c_str()); @@ -553,22 +604,21 @@ void CHyprpaper::renderWallpaperForMonitor(SMonitor* pMonitor) { cairo_restore(PCAIRO); if (pMonitor->pCurrentLayerSurface) { - wl_surface_attach(pMonitor->pCurrentLayerSurface->pSurface, PBUFFER->buffer, 0, 0); - wl_surface_set_buffer_scale(pMonitor->pCurrentLayerSurface->pSurface, pMonitor->pCurrentLayerSurface->pFractionalScaleInfo ? 1 : pMonitor->scale); - wl_surface_damage_buffer(pMonitor->pCurrentLayerSurface->pSurface, 0, 0, 0xFFFF, 0xFFFF); + pMonitor->pCurrentLayerSurface->pSurface->sendAttach(PBUFFER->buffer.get(), 0, 0); + pMonitor->pCurrentLayerSurface->pSurface->sendSetBufferScale(pMonitor->pCurrentLayerSurface->pFractionalScaleInfo ? 1 : pMonitor->scale); + pMonitor->pCurrentLayerSurface->pSurface->sendDamageBuffer(0, 0, 0xFFFF, 0xFFFF); // our wps are always opaque - auto opaqueRegion = wl_compositor_create_region(g_pHyprpaper->m_sCompositor); - wl_region_add(opaqueRegion, 0, 0, PBUFFER->pixelSize.x, PBUFFER->pixelSize.y); - wl_surface_set_opaque_region(pMonitor->pCurrentLayerSurface->pSurface, opaqueRegion); + auto opaqueRegion = makeShared(g_pHyprpaper->m_pCompositor->sendCreateRegion()); + opaqueRegion->sendAdd(0, 0, PBUFFER->pixelSize.x, PBUFFER->pixelSize.y); + pMonitor->pCurrentLayerSurface->pSurface->sendSetOpaqueRegion(opaqueRegion.get()); if (pMonitor->pCurrentLayerSurface->pFractionalScaleInfo) { - Debug::log(LOG, "Submitting viewport dest size %ix%i for %x", static_cast(std::round(pMonitor->size.x)), static_cast(std::round(pMonitor->size.y)), pMonitor->pCurrentLayerSurface); - wp_viewport_set_destination(pMonitor->pCurrentLayerSurface->pViewport, static_cast(std::round(pMonitor->size.x)), static_cast(std::round(pMonitor->size.y))); + Debug::log(LOG, "Submitting viewport dest size %ix%i for %x", static_cast(std::round(pMonitor->size.x)), static_cast(std::round(pMonitor->size.y)), + pMonitor->pCurrentLayerSurface); + pMonitor->pCurrentLayerSurface->pViewport->sendSetDestination(static_cast(std::round(pMonitor->size.x)), static_cast(std::round(pMonitor->size.y))); } - wl_surface_commit(pMonitor->pCurrentLayerSurface->pSurface); - - wl_region_destroy(opaqueRegion); + pMonitor->pCurrentLayerSurface->pSurface->sendCommit(); } // check if we dont need to remove a wallpaper @@ -585,20 +635,18 @@ void CHyprpaper::renderWallpaperForMonitor(SMonitor* pMonitor) { bool CHyprpaper::lockSingleInstance() { const std::string XDG_RUNTIME_DIR = getenv("XDG_RUNTIME_DIR"); - const auto LOCKFILE = XDG_RUNTIME_DIR + "/hyprpaper.lock"; + const auto LOCKFILE = XDG_RUNTIME_DIR + "/hyprpaper.lock"; if (std::filesystem::exists(LOCKFILE)) { std::ifstream ifs(LOCKFILE); - std::string content((std::istreambuf_iterator(ifs)), (std::istreambuf_iterator())); + std::string content((std::istreambuf_iterator(ifs)), (std::istreambuf_iterator())); try { kill(std::stoull(content), 0); if (errno != ESRCH) return false; - } catch (std::exception& e) { - ; - } + } catch (std::exception& e) { ; } } // create lockfile @@ -613,6 +661,6 @@ bool CHyprpaper::lockSingleInstance() { void CHyprpaper::unlockSingleInstance() { const std::string XDG_RUNTIME_DIR = getenv("XDG_RUNTIME_DIR"); - const auto LOCKFILE = XDG_RUNTIME_DIR + "/hyprpaper.lock"; + const auto LOCKFILE = XDG_RUNTIME_DIR + "/hyprpaper.lock"; unlink(LOCKFILE.c_str()); } diff --git a/src/Hyprpaper.hpp b/src/Hyprpaper.hpp index 2c06066..4ab3390 100644 --- a/src/Hyprpaper.hpp +++ b/src/Hyprpaper.hpp @@ -2,7 +2,6 @@ #include "config/ConfigManager.hpp" #include "defines.hpp" -#include "events/Events.hpp" #include "helpers/MiscFunctions.hpp" #include "helpers/Monitor.hpp" #include "helpers/PoolBuffer.hpp" @@ -10,61 +9,72 @@ #include "render/WallpaperTarget.hpp" #include +#include "protocols/cursor-shape-v1.hpp" +#include "protocols/fractional-scale-v1.hpp" +#include "protocols/linux-dmabuf-v1.hpp" +#include "protocols/viewporter.hpp" +#include "protocols/wayland.hpp" +#include "protocols/wlr-layer-shell-unstable-v1.hpp" + struct SWallpaperRenderData { bool contain = false; }; class CHyprpaper { -public: + public: // important - wl_display* m_sDisplay; // assured - wl_compositor* m_sCompositor; // assured - wl_shm* m_sSHM; // assured - zwlr_layer_shell_v1* m_sLayerShell = nullptr; // expected - wp_fractional_scale_manager_v1* m_sFractionalScale = nullptr; // will remain null if not bound - wp_viewporter* m_sViewporter = nullptr; // expected + wl_display* m_sDisplay = nullptr; + SP m_pCompositor; + SP m_pSHM; + SP m_pLayerShell; + SP m_pFractionalScale; + SP m_pViewporter; + SP m_pSeat; + SP m_pSeatPointer; + SP m_pSeatCursorShapeDevice; + SP m_pCursorShape; // init the utility CHyprpaper(); - void init(); - void tick(bool force); + void init(); + void tick(bool force); - std::unordered_map m_mWallpaperTargets; - std::unordered_map m_mMonitorActiveWallpapers; + std::unordered_map m_mWallpaperTargets; + std::unordered_map m_mMonitorActiveWallpapers; std::unordered_map m_mMonitorWallpaperRenderData; - std::unordered_map m_mMonitorActiveWallpaperTargets; - std::vector> m_vBuffers; - std::vector> m_vMonitors; + std::unordered_map m_mMonitorActiveWallpaperTargets; + std::vector> m_vBuffers; + std::vector> m_vMonitors; - std::string m_szExplicitConfigPath; - bool m_bNoFractionalScale = false; + std::string m_szExplicitConfigPath; + bool m_bNoFractionalScale = false; - void removeOldHyprpaperImages(); - void preloadAllWallpapersFromConfig(); - void recheckAllMonitors(); - void ensureMonitorHasActiveWallpaper(SMonitor*); - void createLSForMonitor(SMonitor*); - void renderWallpaperForMonitor(SMonitor*); - void createBuffer(SPoolBuffer*, int32_t, int32_t, uint32_t); - void destroyBuffer(SPoolBuffer*); - int createPoolFile(size_t, std::string&); - bool setCloexec(const int&); - void clearWallpaperFromMonitor(const std::string&); - SMonitor* getMonitorFromName(const std::string&); - bool isPreloaded(const std::string&); - void recheckMonitor(SMonitor*); - void ensurePoolBuffersPresent(); - SPoolBuffer* getPoolBuffer(SMonitor*, CWallpaperTarget*); - void unloadWallpaper(const std::string&); - void createSeat(wl_seat*); - bool lockSingleInstance(); // fails on multi-instance - void unlockSingleInstance(); + void removeOldHyprpaperImages(); + void preloadAllWallpapersFromConfig(); + void recheckAllMonitors(); + void ensureMonitorHasActiveWallpaper(SMonitor*); + void createLSForMonitor(SMonitor*); + void renderWallpaperForMonitor(SMonitor*); + void createBuffer(SPoolBuffer*, int32_t, int32_t, uint32_t); + void destroyBuffer(SPoolBuffer*); + int createPoolFile(size_t, std::string&); + bool setCloexec(const int&); + void clearWallpaperFromMonitor(const std::string&); + SMonitor* getMonitorFromName(const std::string&); + bool isPreloaded(const std::string&); + void recheckMonitor(SMonitor*); + void ensurePoolBuffersPresent(); + SPoolBuffer* getPoolBuffer(SMonitor*, CWallpaperTarget*); + void unloadWallpaper(const std::string&); + void createSeat(SP); + bool lockSingleInstance(); // fails on multi-instance + void unlockSingleInstance(); - std::mutex m_mtTickMutex; + std::mutex m_mtTickMutex; - SMonitor* m_pLastMonitor = nullptr; + SMonitor* m_pLastMonitor = nullptr; -private: + private: bool m_bShouldExit = false; }; diff --git a/src/config/ConfigManager.cpp b/src/config/ConfigManager.cpp index a407e57..212b6b2 100644 --- a/src/config/ConfigManager.cpp +++ b/src/config/ConfigManager.cpp @@ -1,6 +1,7 @@ #include "ConfigManager.hpp" #include "../Hyprpaper.hpp" #include +#include static Hyprlang::CParseResult handleWallpaper(const char* C, const char* V) { const std::string COMMAND = C; @@ -12,19 +13,19 @@ static Hyprlang::CParseResult handleWallpaper(const char* C, const char* V) { return result; } - auto MONITOR = VALUE.substr(0, VALUE.find_first_of(',')); + auto MONITOR = VALUE.substr(0, VALUE.find_first_of(',')); auto WALLPAPER = g_pConfigManager->trimPath(VALUE.substr(VALUE.find_first_of(',') + 1)); bool contain = false; if (WALLPAPER.find("contain:") == 0) { WALLPAPER = WALLPAPER.substr(8); - contain = true; + contain = true; } if (WALLPAPER[0] == '~') { static const char* const ENVHOME = getenv("HOME"); - WALLPAPER = std::string(ENVHOME) + WALLPAPER.substr(1); + WALLPAPER = std::string(ENVHOME) + WALLPAPER.substr(1); } std::error_code ec; @@ -34,20 +35,21 @@ static Hyprlang::CParseResult handleWallpaper(const char* C, const char* V) { return result; } - if (std::find(g_pConfigManager->m_dRequestedPreloads.begin(), g_pConfigManager->m_dRequestedPreloads.end(), WALLPAPER) == g_pConfigManager->m_dRequestedPreloads.end() && !g_pHyprpaper->isPreloaded(WALLPAPER)) { + if (std::find(g_pConfigManager->m_dRequestedPreloads.begin(), g_pConfigManager->m_dRequestedPreloads.end(), WALLPAPER) == g_pConfigManager->m_dRequestedPreloads.end() && + !g_pHyprpaper->isPreloaded(WALLPAPER)) { result.setError("wallpaper failed (not preloaded)"); return result; } g_pHyprpaper->clearWallpaperFromMonitor(MONITOR); - g_pHyprpaper->m_mMonitorActiveWallpapers[MONITOR] = WALLPAPER; + g_pHyprpaper->m_mMonitorActiveWallpapers[MONITOR] = WALLPAPER; g_pHyprpaper->m_mMonitorWallpaperRenderData[MONITOR].contain = contain; if (MONITOR.empty()) { for (auto& m : g_pHyprpaper->m_vMonitors) { if (!m->hasATarget || m->wildcard) { g_pHyprpaper->clearWallpaperFromMonitor(m->name); - g_pHyprpaper->m_mMonitorActiveWallpapers[m->name] = WALLPAPER; + g_pHyprpaper->m_mMonitorActiveWallpapers[m->name] = WALLPAPER; g_pHyprpaper->m_mMonitorWallpaperRenderData[m->name].contain = contain; } } @@ -61,13 +63,13 @@ static Hyprlang::CParseResult handleWallpaper(const char* C, const char* V) { } static Hyprlang::CParseResult handlePreload(const char* C, const char* V) { - const std::string COMMAND = C; - const std::string VALUE = V; - auto WALLPAPER = VALUE; + const std::string COMMAND = C; + const std::string VALUE = V; + auto WALLPAPER = VALUE; if (WALLPAPER[0] == '~') { static const char* const ENVHOME = getenv("HOME"); - WALLPAPER = std::string(ENVHOME) + WALLPAPER.substr(1); + WALLPAPER = std::string(ENVHOME) + WALLPAPER.substr(1); } std::error_code ec; @@ -84,8 +86,8 @@ static Hyprlang::CParseResult handlePreload(const char* C, const char* V) { } static Hyprlang::CParseResult handleUnloadAll(const char* C, const char* V) { - const std::string COMMAND = C; - const std::string VALUE = V; + const std::string COMMAND = C; + const std::string VALUE = V; std::vector toUnload; for (auto& [name, target] : g_pHyprpaper->m_mWallpaperTargets) { @@ -112,16 +114,16 @@ static Hyprlang::CParseResult handleUnloadAll(const char* C, const char* V) { } static Hyprlang::CParseResult handleUnload(const char* C, const char* V) { - const std::string COMMAND = C; - const std::string VALUE = V; - auto WALLPAPER = VALUE; + const std::string COMMAND = C; + const std::string VALUE = V; + auto WALLPAPER = VALUE; if (VALUE == "all" || VALUE == "unused") return handleUnloadAll(C, V); if (WALLPAPER[0] == '~') { static const char* const ENVHOME = getenv("HOME"); - WALLPAPER = std::string(ENVHOME) + WALLPAPER.substr(1); + WALLPAPER = std::string(ENVHOME) + WALLPAPER.substr(1); } g_pHyprpaper->unloadWallpaper(WALLPAPER); @@ -131,9 +133,9 @@ static Hyprlang::CParseResult handleUnload(const char* C, const char* V) { static Hyprlang::CParseResult handleReload(const char* C, const char* V) { const std::string COMMAND = C; - const std::string VALUE = V; + const std::string VALUE = V; - auto WALLPAPER = g_pConfigManager->trimPath(VALUE.substr(VALUE.find_first_of(',') + 1)); + auto WALLPAPER = g_pConfigManager->trimPath(VALUE.substr(VALUE.find_first_of(',') + 1)); if (WALLPAPER.find("contain:") == 0) { WALLPAPER = WALLPAPER.substr(8); @@ -189,8 +191,7 @@ void CConfigManager::parse() { const auto ERROR = config->parse(); if (ERROR.error) - std::cout << "Error in config: \n" - << ERROR.getError() << "\n"; + std::cout << "Error in config: \n" << ERROR.getError() << "\n"; } std::string CConfigManager::getMainConfigPath() { @@ -211,6 +212,6 @@ std::string CConfigManager::trimPath(std::string path) { // trims whitespaces, tabs and new line feeds size_t pathStartIndex = path.find_first_not_of(" \t\r\n"); - size_t pathEndIndex = path.find_last_not_of(" \t\r\n"); + size_t pathEndIndex = path.find_last_not_of(" \t\r\n"); return path.substr(pathStartIndex, pathEndIndex - pathStartIndex + 1); } diff --git a/src/config/ConfigManager.hpp b/src/config/ConfigManager.hpp index 67700e1..766a398 100644 --- a/src/config/ConfigManager.hpp +++ b/src/config/ConfigManager.hpp @@ -5,18 +5,18 @@ class CIPCSocket; class CConfigManager { -public: + public: // gets all the data from the config CConfigManager(); - void parse(); + void parse(); - std::deque m_dRequestedPreloads; - std::string getMainConfigPath(); - std::string trimPath(std::string path); + std::deque m_dRequestedPreloads; + std::string getMainConfigPath(); + std::string trimPath(std::string path); std::unique_ptr config; -private: + private: friend class CIPCSocket; }; diff --git a/src/debug/Log.cpp b/src/debug/Log.cpp index ff145d4..bf3574d 100644 --- a/src/debug/Log.cpp +++ b/src/debug/Log.cpp @@ -9,28 +9,17 @@ void Debug::log(LogLevel level, const char* fmt, ...) { std::string levelstr = ""; switch (level) { - case LOG: - levelstr = "[LOG] "; - break; - case WARN: - levelstr = "[WARN] "; - break; - case ERR: - levelstr = "[ERR] "; - break; - case CRIT: - levelstr = "[CRITICAL] "; - break; - case INFO: - levelstr = "[INFO] "; - break; - default: - break; + case LOG: levelstr = "[LOG] "; break; + case WARN: levelstr = "[WARN] "; break; + case ERR: levelstr = "[ERR] "; break; + case CRIT: levelstr = "[CRITICAL] "; break; + case INFO: levelstr = "[INFO] "; break; + default: break; } - char buf[LOGMESSAGESIZE] = ""; - char* outputStr; - int logLen; + char buf[LOGMESSAGESIZE] = ""; + char* outputStr; + int logLen; va_list args; va_start(args, fmt); diff --git a/src/debug/Log.hpp b/src/debug/Log.hpp index 0fd16cf..211a575 100644 --- a/src/debug/Log.hpp +++ b/src/debug/Log.hpp @@ -5,7 +5,7 @@ enum LogLevel { NONE = -1, - LOG = 0, + LOG = 0, WARN, ERR, CRIT, diff --git a/src/defines.hpp b/src/defines.hpp index 738148f..67337d8 100644 --- a/src/defines.hpp +++ b/src/defines.hpp @@ -2,7 +2,6 @@ #include "includes.hpp" #include "debug/Log.hpp" -#include "helpers/Vector2D.hpp" // git stuff #ifndef GIT_COMMIT_HASH @@ -16,4 +15,12 @@ #endif #ifndef GIT_DIRTY #define GIT_DIRTY "?" -#endif \ No newline at end of file +#endif + +#include +using namespace Hyprutils::Math; + +#include +using namespace Hyprutils::Memory; +#define SP Hyprutils::Memory::CSharedPointer +#define WP Hyprutils::Memory::CWeakPointer diff --git a/src/events/Events.cpp b/src/events/Events.cpp deleted file mode 100644 index 2be8249..0000000 --- a/src/events/Events.cpp +++ /dev/null @@ -1,164 +0,0 @@ -#include "Events.hpp" -#include "../Hyprpaper.hpp" - -void Events::geometry(void* data, wl_output* output, int32_t x, int32_t y, int32_t width_mm, int32_t height_mm, int32_t subpixel, const char* make, const char* model, int32_t transform) { - // ignored -} - -void Events::mode(void* data, wl_output* output, uint32_t flags, int32_t width, int32_t height, int32_t refresh) { - const auto PMONITOR = (SMonitor*)data; - - PMONITOR->size = Vector2D(width, height); -} - -void Events::done(void* data, wl_output* wl_output) { - const auto PMONITOR = (SMonitor*)data; - - PMONITOR->readyForLS = true; - - std::lock_guard lg(g_pHyprpaper->m_mtTickMutex); - if (g_pConfigManager) // don't tick if this is the first roundtrip - g_pHyprpaper->tick(true); -} - -void Events::scale(void* data, wl_output* wl_output, int32_t scale) { - const auto PMONITOR = (SMonitor*)data; - - PMONITOR->scale = scale; -} - -void Events::name(void* data, wl_output* wl_output, const char* name) { - const auto PMONITOR = (SMonitor*)data; - - PMONITOR->name = name; -} - -void Events::description(void* data, wl_output* wl_output, const char* description) { - const auto PMONITOR = (SMonitor*)data; - // remove comma character from description. This allow monitor specific rules to work on monitor with comma on their description - std::string m_description = description; - std::erase(m_description, ','); - - PMONITOR->description = m_description; -} - -void Events::handleCapabilities(void* data, wl_seat* wl_seat, uint32_t capabilities) { - if (capabilities & WL_SEAT_CAPABILITY_POINTER) { - wl_pointer_add_listener(wl_seat_get_pointer(wl_seat), &pointerListener, wl_seat); - } -} - -void Events::handlePointerLeave(void* data, struct wl_pointer* wl_pointer, uint32_t serial, struct wl_surface* surface) { - // ignored - wl_surface_commit(surface); - - g_pHyprpaper->m_pLastMonitor = nullptr; -} - -void Events::handlePointerAxis(void* data, wl_pointer* wl_pointer, uint32_t time, uint32_t axis, wl_fixed_t value) { - // ignored -} - -void Events::handlePointerMotion(void* data, struct wl_pointer* wl_pointer, uint32_t time, wl_fixed_t surface_x, wl_fixed_t surface_y) { - // ignored - if (g_pHyprpaper->m_pLastMonitor) { - wl_surface_commit(g_pHyprpaper->m_pLastMonitor->pCurrentLayerSurface->pSurface); - } -} - -void Events::handlePointerButton(void* data, struct wl_pointer* wl_pointer, uint32_t serial, uint32_t time, uint32_t button, uint32_t button_state) { - // ignored -} - -void Events::handlePointerEnter(void* data, struct wl_pointer* wl_pointer, uint32_t serial, struct wl_surface* surface, wl_fixed_t surface_x, wl_fixed_t surface_y) { - for (auto& mon : g_pHyprpaper->m_vMonitors) { - if (mon->pCurrentLayerSurface->pSurface == surface) { - g_pHyprpaper->m_pLastMonitor = mon.get(); - - wl_surface_set_buffer_scale(mon->pCurrentLayerSurface->pCursorSurface, mon->scale); - wl_surface_attach(mon->pCurrentLayerSurface->pCursorSurface, wl_cursor_image_get_buffer(mon->pCurrentLayerSurface->pCursorImg), 0, 0); - wl_pointer_set_cursor(wl_pointer, serial, mon->pCurrentLayerSurface->pCursorSurface, mon->pCurrentLayerSurface->pCursorImg->hotspot_x / mon->scale, mon->pCurrentLayerSurface->pCursorImg->hotspot_y / mon->scale); - wl_surface_commit(mon->pCurrentLayerSurface->pCursorSurface); - } - } -} - -void Events::ls_configure(void* data, zwlr_layer_surface_v1* surface, uint32_t serial, uint32_t width, uint32_t height) { - const auto PLAYERSURFACE = (CLayerSurface*)data; - - PLAYERSURFACE->m_pMonitor->size = Vector2D(width, height); - PLAYERSURFACE->m_pMonitor->wantsReload = true; - PLAYERSURFACE->m_pMonitor->configureSerial = serial; - PLAYERSURFACE->m_pMonitor->wantsACK = true; - PLAYERSURFACE->m_pMonitor->initialized = true; - - Debug::log(LOG, "configure for %s", PLAYERSURFACE->m_pMonitor->name.c_str()); -} - -void Events::handleLSClosed(void* data, zwlr_layer_surface_v1* zwlr_layer_surface_v1) { - const auto PLAYERSURFACE = (CLayerSurface*)data; - - for (auto& m : g_pHyprpaper->m_vMonitors) { - std::erase_if(m->layerSurfaces, [&](const auto& other) { return other.get() == PLAYERSURFACE; }); - if (m->pCurrentLayerSurface == PLAYERSURFACE) { - if (m->layerSurfaces.empty()) { - m->pCurrentLayerSurface = nullptr; - } else { - m->pCurrentLayerSurface = m->layerSurfaces.begin()->get(); - g_pHyprpaper->recheckMonitor(m.get()); - } - } - } -} - -void Events::handleGlobal(void* data, struct wl_registry* registry, uint32_t name, const char* interface, uint32_t version) { - if (strcmp(interface, wl_compositor_interface.name) == 0) { - g_pHyprpaper->m_sCompositor = (wl_compositor*)wl_registry_bind(registry, name, &wl_compositor_interface, 4); - } else if (strcmp(interface, wl_shm_interface.name) == 0) { - g_pHyprpaper->m_sSHM = (wl_shm*)wl_registry_bind(registry, name, &wl_shm_interface, 1); - } else if (strcmp(interface, wl_output_interface.name) == 0) { - g_pHyprpaper->m_mtTickMutex.lock(); - - const auto PMONITOR = g_pHyprpaper->m_vMonitors.emplace_back(std::make_unique()).get(); - PMONITOR->wayland_name = name; - PMONITOR->name = ""; - PMONITOR->output = (wl_output*)wl_registry_bind(registry, name, &wl_output_interface, 4); - wl_output_add_listener(PMONITOR->output, &Events::outputListener, PMONITOR); - - g_pHyprpaper->m_mtTickMutex.unlock(); - } else if (strcmp(interface, wl_seat_interface.name) == 0) { - g_pHyprpaper->createSeat((wl_seat*)wl_registry_bind(registry, name, &wl_seat_interface, 1)); - } else if (strcmp(interface, zwlr_layer_shell_v1_interface.name) == 0) { - g_pHyprpaper->m_sLayerShell = (zwlr_layer_shell_v1*)wl_registry_bind(registry, name, &zwlr_layer_shell_v1_interface, 1); - } else if (strcmp(interface, wp_fractional_scale_manager_v1_interface.name) == 0 && !g_pHyprpaper->m_bNoFractionalScale) { - g_pHyprpaper->m_sFractionalScale = (wp_fractional_scale_manager_v1*)wl_registry_bind(registry, name, &wp_fractional_scale_manager_v1_interface, 1); - } else if (strcmp(interface, wp_viewporter_interface.name) == 0) { - g_pHyprpaper->m_sViewporter = (wp_viewporter*)wl_registry_bind(registry, name, &wp_viewporter_interface, 1); - } -} - -void Events::handleGlobalRemove(void* data, struct wl_registry* registry, uint32_t name) { - for (auto& m : g_pHyprpaper->m_vMonitors) { - if (m->wayland_name == name) { - Debug::log(LOG, "Destroying output %s", m->name.c_str()); - g_pHyprpaper->clearWallpaperFromMonitor(m->name); - std::erase_if(g_pHyprpaper->m_vMonitors, [&](const auto& other) { return other->wayland_name == name; }); - return; - } - } -} - -void Events::handlePreferredScale(void* data, wp_fractional_scale_v1* fractionalScaleInfo, uint32_t scale) { - const double SCALE = scale / 120.0; - - CLayerSurface* const pLS = (CLayerSurface*)data; - - Debug::log(LOG, "handlePreferredScale: %.2lf for %lx", SCALE, pLS); - - if (pLS->fScale != SCALE) { - pLS->fScale = SCALE; - std::lock_guard lg(g_pHyprpaper->m_mtTickMutex); - pLS->m_pMonitor->wantsReload = true; - g_pHyprpaper->tick(true); - } -} diff --git a/src/events/Events.hpp b/src/events/Events.hpp deleted file mode 100644 index d3e9edb..0000000 --- a/src/events/Events.hpp +++ /dev/null @@ -1,51 +0,0 @@ -#pragma once - -#include "../defines.hpp" - -namespace Events { - void geometry(void *data, wl_output *output, int32_t x, int32_t y, int32_t width_mm, int32_t height_mm, int32_t subpixel, const char *make, const char *model, int32_t transform); - - void mode(void *data, wl_output *output, uint32_t flags, int32_t width, int32_t height, int32_t refresh); - - void done(void *data, wl_output *wl_output); - - void scale(void *data, wl_output *wl_output, int32_t scale); - - void name(void *data, wl_output *wl_output, const char *name); - - void description(void *data, wl_output *wl_output, const char *description); - - void ls_configure(void *data, zwlr_layer_surface_v1 *surface, uint32_t serial, uint32_t width, uint32_t height); - - void handleLSClosed(void *data, zwlr_layer_surface_v1 *zwlr_layer_surface_v1); - - void handleGlobal(void *data, struct wl_registry *registry, uint32_t name, const char *interface, uint32_t version); - - void handleGlobalRemove(void *data, struct wl_registry *registry, uint32_t name); - - void handleCapabilities(void *data, wl_seat *wl_seat, uint32_t capabilities); - - void handlePointerMotion(void *data, struct wl_pointer *wl_pointer, uint32_t time, wl_fixed_t surface_x, wl_fixed_t surface_y); - - void handlePointerButton(void *data, struct wl_pointer *wl_pointer, uint32_t serial, uint32_t time, uint32_t button, uint32_t button_state); - - void handlePointerAxis(void *data, wl_pointer *wl_pointer, uint32_t time, uint32_t axis, wl_fixed_t value); - - void handlePointerEnter(void *data, struct wl_pointer *wl_pointer, uint32_t serial, struct wl_surface *surface, wl_fixed_t surface_x, wl_fixed_t surface_y); - - void handlePointerLeave(void *data, struct wl_pointer *wl_pointer, uint32_t serial, struct wl_surface *surface); - - void handlePreferredScale(void *data, wp_fractional_scale_v1 *wp_fractional_scale_v1, uint32_t scale); - - inline const wl_output_listener outputListener = {.geometry = geometry, .mode = mode, .done = done, .scale = scale, .name = name, .description = description}; - - inline const zwlr_layer_surface_v1_listener layersurfaceListener = { .configure = ls_configure, .closed = handleLSClosed }; - - inline const struct wl_registry_listener registryListener = { .global = handleGlobal, .global_remove = handleGlobalRemove }; - - inline const wl_pointer_listener pointerListener = { .enter = handlePointerEnter, .leave = handlePointerLeave, .motion = handlePointerMotion, .button = handlePointerButton, .axis = handlePointerAxis }; - - inline const wl_seat_listener seatListener = { .capabilities = handleCapabilities }; - - inline const wp_fractional_scale_v1_listener scaleListener = { .preferred_scale = handlePreferredScale }; -} diff --git a/src/helpers/Bmp.cpp b/src/helpers/Bmp.cpp index 96afea4..b92460d 100644 --- a/src/helpers/Bmp.cpp +++ b/src/helpers/Bmp.cpp @@ -3,25 +3,26 @@ #include #include #include +#include class BmpHeader { -public: + public: unsigned char format[2]; - uint32_t sizeOfFile; - uint16_t reserved1; - uint16_t reserved2; - uint32_t dataOffset; - uint32_t sizeOfBitmapHeader; - uint32_t width; - uint32_t height; - uint16_t numberOfColors; - uint16_t numberOfBitPerPixel; - uint32_t compressionMethod; - uint32_t imageSize; - uint32_t horizontalResolutionPPM; - uint32_t verticalResolutionPPM; - uint32_t numberOfCollors; - uint32_t numberOfImportantCollors; + uint32_t sizeOfFile; + uint16_t reserved1; + uint16_t reserved2; + uint32_t dataOffset; + uint32_t sizeOfBitmapHeader; + uint32_t width; + uint32_t height; + uint16_t numberOfColors; + uint16_t numberOfBitPerPixel; + uint32_t compressionMethod; + uint32_t imageSize; + uint32_t horizontalResolutionPPM; + uint32_t verticalResolutionPPM; + uint32_t numberOfCollors; + uint32_t numberOfImportantCollors; BmpHeader(std::ifstream& file) { file.seekg(0, std::ios::end); @@ -59,7 +60,7 @@ public: if (!imageSize) imageSize = sizeOfFile - dataOffset; - if (imageSize != (width * height * numberOfBitPerPixel/8)) { + if (imageSize != (width * height * numberOfBitPerPixel / 8)) { Debug::log(ERR, "Unable to parse bitmap header: wrong image size"); exit(1); } @@ -69,8 +70,8 @@ public: }; void reflectImage(unsigned char* image, uint32_t numberOfRows, int stride) { - int rowStart = 0; - int rowEnd = numberOfRows - 1; + int rowStart = 0; + int rowEnd = numberOfRows - 1; std::vector temp; temp.resize(stride); while (rowStart < rowEnd) { @@ -83,8 +84,8 @@ void reflectImage(unsigned char* image, uint32_t numberOfRows, int stride) { }; void convertRgbToArgb(std::ifstream& imageStream, unsigned char* outputImage, uint32_t newImageSize) { - uint8_t forthBitCounter = 0; - unsigned long imgCursor = 0; + uint8_t forthBitCounter = 0; + unsigned long imgCursor = 0; while (imgCursor < newImageSize) { imageStream.read(reinterpret_cast(&outputImage[imgCursor]), 1); imgCursor++; @@ -104,12 +105,12 @@ cairo_surface_t* BMP::createSurfaceFromBMP(const std::string& path) { exit(1); } - std::ifstream bitmapImageStream(path); - BmpHeader bitmapHeader(bitmapImageStream); + std::ifstream bitmapImageStream(path); + BmpHeader bitmapHeader(bitmapImageStream); - cairo_format_t format = CAIRO_FORMAT_ARGB32; - int stride = cairo_format_stride_for_width (format, bitmapHeader.width); - unsigned char* imageData = (unsigned char*) malloc(bitmapHeader.height * stride); + cairo_format_t format = CAIRO_FORMAT_ARGB32; + int stride = cairo_format_stride_for_width(format, bitmapHeader.width); + unsigned char* imageData = (unsigned char*)malloc(bitmapHeader.height * stride); if (bitmapHeader.numberOfBitPerPixel == 24) convertRgbToArgb(bitmapImageStream, imageData, bitmapHeader.height * stride); diff --git a/src/helpers/Jpeg.cpp b/src/helpers/Jpeg.cpp index 833f88a..9e6f8d6 100644 --- a/src/helpers/Jpeg.cpp +++ b/src/helpers/Jpeg.cpp @@ -3,6 +3,7 @@ #include #include #include +#include cairo_surface_t* JPEG::createSurfaceFromJPEG(const std::string& path) { @@ -16,11 +17,11 @@ cairo_surface_t* JPEG::createSurfaceFromJPEG(const std::string& path) { exit(1); } - void* imageRawData; + void* imageRawData; struct stat fileInfo = {}; - const auto FD = open(path.c_str(), O_RDONLY); + const auto FD = open(path.c_str(), O_RDONLY); fstat(FD, &fileInfo); @@ -33,7 +34,7 @@ cairo_surface_t* JPEG::createSurfaceFromJPEG(const std::string& path) { // now the JPEG is in the memory jpeg_decompress_struct decompressStruct = {}; - jpeg_error_mgr errorManager = {}; + jpeg_error_mgr errorManager = {}; decompressStruct.err = jpeg_std_error(&errorManager); jpeg_create_decompress(&decompressStruct); @@ -56,13 +57,13 @@ cairo_surface_t* JPEG::createSurfaceFromJPEG(const std::string& path) { exit(1); } - const auto CAIRODATA = cairo_image_surface_get_data(cairoSurface); + const auto CAIRODATA = cairo_image_surface_get_data(cairoSurface); const auto CAIROSTRIDE = cairo_image_surface_get_stride(cairoSurface); - JSAMPROW rowRead; + JSAMPROW rowRead; while (decompressStruct.output_scanline < decompressStruct.output_height) { const auto PROW = CAIRODATA + (decompressStruct.output_scanline * CAIROSTRIDE); - rowRead = PROW; + rowRead = PROW; jpeg_read_scanlines(&decompressStruct, &rowRead, 1); } diff --git a/src/helpers/MiscFunctions.hpp b/src/helpers/MiscFunctions.hpp index 9b76297..5b82ae1 100644 --- a/src/helpers/MiscFunctions.hpp +++ b/src/helpers/MiscFunctions.hpp @@ -1,7 +1,7 @@ #pragma once #include -#include "Vector2D.hpp" +#include "../defines.hpp" -bool vectorDeltaLessThan(const Vector2D& a, const Vector2D& b, const float& delta); -bool vectorDeltaLessThan(const Vector2D& a, const Vector2D& b, const Vector2D& delta); +bool vectorDeltaLessThan(const Vector2D& a, const Vector2D& b, const float& delta); +bool vectorDeltaLessThan(const Vector2D& a, const Vector2D& b, const Vector2D& delta); std::string execAndGet(const char*); \ No newline at end of file diff --git a/src/helpers/Monitor.cpp b/src/helpers/Monitor.cpp new file mode 100644 index 0000000..e9ef53b --- /dev/null +++ b/src/helpers/Monitor.cpp @@ -0,0 +1,24 @@ +#include "Monitor.hpp" +#include "../Hyprpaper.hpp" + +void SMonitor::registerListeners() { + output->setMode([this](CCWlOutput* r, uint32_t flags, int32_t width, int32_t height, int32_t refresh) { size = Vector2D(width, height); }); + + output->setDone([this](CCWlOutput* r) { + readyForLS = true; + std::lock_guard lg(g_pHyprpaper->m_mtTickMutex); + if (g_pConfigManager) // don't tick if this is the first roundtrip + g_pHyprpaper->tick(true); + }); + + output->setScale([this](CCWlOutput* r, int32_t scale_) { scale = scale_; }); + + output->setName([this](CCWlOutput* r, const char* name_) { name = name_; }); + + output->setDescription([this](CCWlOutput* r, const char* desc_) { + std::string desc = desc_; + std::erase(desc, ','); + + description = desc; + }); +} \ No newline at end of file diff --git a/src/helpers/Monitor.hpp b/src/helpers/Monitor.hpp index 97a78db..937a02a 100644 --- a/src/helpers/Monitor.hpp +++ b/src/helpers/Monitor.hpp @@ -3,27 +3,30 @@ #include "../defines.hpp" #include "../render/LayerSurface.hpp" #include "PoolBuffer.hpp" +#include "protocols/wayland.hpp" struct SMonitor { - std::string name = ""; - std::string description = ""; - wl_output* output = nullptr; - uint32_t wayland_name = 0; - Vector2D size; - int scale; + std::string name = ""; + std::string description = ""; + SP output; + uint32_t wayland_name = 0; + Vector2D size; + int scale; - bool readyForLS = false; - bool hasATarget = true; + bool readyForLS = false; + bool hasATarget = true; - bool wildcard = true; + bool wildcard = true; - uint32_t configureSerial = 0; - SPoolBuffer buffer; + uint32_t configureSerial = 0; + SPoolBuffer buffer; - bool wantsReload = false; - bool wantsACK = false; - bool initialized = false; + bool wantsReload = false; + bool wantsACK = false; + bool initialized = false; std::vector> layerSurfaces; - CLayerSurface* pCurrentLayerSurface = nullptr; + CLayerSurface* pCurrentLayerSurface = nullptr; + + void registerListeners(); }; \ No newline at end of file diff --git a/src/helpers/PoolBuffer.hpp b/src/helpers/PoolBuffer.hpp index beba476..cfe1a0f 100644 --- a/src/helpers/PoolBuffer.hpp +++ b/src/helpers/PoolBuffer.hpp @@ -1,17 +1,18 @@ #pragma once #include "../defines.hpp" +#include "protocols/wayland.hpp" class CWallpaperTarget; struct SPoolBuffer { - wl_buffer* buffer = nullptr; + SP buffer = nullptr; cairo_surface_t* surface = nullptr; - cairo_t* cairo = nullptr; - void* data = nullptr; - size_t size = 0; - std::string name = ""; + cairo_t* cairo = nullptr; + void* data = nullptr; + size_t size = 0; + std::string name = ""; - std::string target = ""; - Vector2D pixelSize; + std::string target = ""; + Vector2D pixelSize; }; \ No newline at end of file diff --git a/src/helpers/Vector2D.cpp b/src/helpers/Vector2D.cpp deleted file mode 100644 index 7071a8e..0000000 --- a/src/helpers/Vector2D.cpp +++ /dev/null @@ -1,23 +0,0 @@ -#include "Vector2D.hpp" - -Vector2D::Vector2D(double xx, double yy) { - x = xx; - y = yy; -} - -Vector2D::Vector2D() { x = 0; y = 0; } -Vector2D::~Vector2D() = default; - -double Vector2D::normalize() { - // get max abs - const auto max = abs(x) > abs(y) ? abs(x) : abs(y); - - x /= max; - y /= max; - - return max; -} - -Vector2D Vector2D::floor() const { - return {static_cast(x), static_cast(y)}; -} diff --git a/src/helpers/Vector2D.hpp b/src/helpers/Vector2D.hpp deleted file mode 100644 index b347aa1..0000000 --- a/src/helpers/Vector2D.hpp +++ /dev/null @@ -1,39 +0,0 @@ -#pragma once - -#include - -class Vector2D { - public: - Vector2D(double, double); - Vector2D(); - ~Vector2D(); - - double x = 0; - double y = 0; - - // returns the scale - double normalize(); - - Vector2D operator+(const Vector2D a) const { - return Vector2D(this->x + a.x, this->y + a.y); - } - Vector2D operator-(const Vector2D a) const { - return Vector2D(this->x - a.x, this->y - a.y); - } - Vector2D operator*(const float a) const { - return Vector2D(this->x * a, this->y * a); - } - Vector2D operator/(const float a) const { - return Vector2D(this->x / a, this->y / a); - } - - bool operator==(const Vector2D& a) const { - return a.x == x && a.y == y; - } - - bool operator!=(const Vector2D& a) const { - return a.x != x || a.y != y; - } - - Vector2D floor() const; -}; diff --git a/src/helpers/Webp.cpp b/src/helpers/Webp.cpp index 4b90597..8eb997b 100644 --- a/src/helpers/Webp.cpp +++ b/src/helpers/Webp.cpp @@ -4,6 +4,7 @@ #include #include +#include #include cairo_surface_t* WEBP::createSurfaceFromWEBP(const std::string& path) { @@ -13,11 +14,11 @@ cairo_surface_t* WEBP::createSurfaceFromWEBP(const std::string& path) { exit(1); } - void* imageRawData; + void* imageRawData; struct stat fileInfo = {}; - const auto FD = open(path.c_str(), O_RDONLY); + const auto FD = open(path.c_str(), O_RDONLY); fstat(FD, &fileInfo); @@ -42,32 +43,31 @@ cairo_surface_t* WEBP::createSurfaceFromWEBP(const std::string& path) { } const auto HEIGHT = config.input.height; - const auto WIDTH = config.input.width; + const auto WIDTH = config.input.width; - auto cairoSurface = cairo_image_surface_create(CAIRO_FORMAT_ARGB32, WIDTH, HEIGHT); + auto cairoSurface = cairo_image_surface_create(CAIRO_FORMAT_ARGB32, WIDTH, HEIGHT); if (cairo_surface_status(cairoSurface) != CAIRO_STATUS_SUCCESS) { Debug::log(CRIT, "createSurfaceFromWEBP: Cairo Failed (?)"); cairo_surface_destroy(cairoSurface); exit(1); } - #if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__ config.output.colorspace = MODE_bgrA; #else config.output.colorspace = MODE_Argb; #endif - const auto CAIRODATA = cairo_image_surface_get_data(cairoSurface); + const auto CAIRODATA = cairo_image_surface_get_data(cairoSurface); const auto CAIROSTRIDE = cairo_image_surface_get_stride(cairoSurface); config.options.no_fancy_upsampling = 1; - config.output.u.RGBA.rgba = CAIRODATA; - config.output.u.RGBA.stride = CAIROSTRIDE; - config.output.u.RGBA.size = CAIROSTRIDE * HEIGHT; - config.output.is_external_memory = 1; - config.output.width = WIDTH; - config.output.height = HEIGHT; + config.output.u.RGBA.rgba = CAIRODATA; + config.output.u.RGBA.stride = CAIROSTRIDE; + config.output.u.RGBA.size = CAIROSTRIDE * HEIGHT; + config.output.is_external_memory = 1; + config.output.width = WIDTH; + config.output.height = HEIGHT; if (WebPDecode((const unsigned char*)imageRawData, fileInfo.st_size, &config) != VP8_STATUS_OK) { Debug::log(CRIT, "createSurfaceFromWEBP: WebP Decode Failed (?)"); @@ -80,5 +80,4 @@ cairo_surface_t* WEBP::createSurfaceFromWEBP(const std::string& path) { WebPFreeDecBuffer(&config.output); return cairoSurface; - } diff --git a/src/includes.hpp b/src/includes.hpp index b840fce..a35a611 100644 --- a/src/includes.hpp +++ b/src/includes.hpp @@ -10,23 +10,6 @@ #include #include -#define class _class -#define namespace _namespace -#define static - -extern "C" { -#include "wlr-layer-shell-unstable-v1-protocol.h" -#include "xdg-shell-protocol.h" -#include "fractional-scale-v1-protocol.h" -#include "viewporter-protocol.h" -#include -#include -} - -#undef class -#undef namespace -#undef static - #include #include #include @@ -38,9 +21,4 @@ extern "C" { #include #include #include -#include - -#include -#include -#include -#include +#include \ No newline at end of file diff --git a/src/ipc/Socket.cpp b/src/ipc/Socket.cpp index c857395..852b79f 100644 --- a/src/ipc/Socket.cpp +++ b/src/ipc/Socket.cpp @@ -12,6 +12,7 @@ #include #include #include +#include void CIPCSocket::initialize() { std::thread([&]() { @@ -22,15 +23,15 @@ void CIPCSocket::initialize() { return; } - sockaddr_un SERVERADDRESS = {.sun_family = AF_UNIX}; + sockaddr_un SERVERADDRESS = {.sun_family = AF_UNIX}; - const auto HISenv = getenv("HYPRLAND_INSTANCE_SIGNATURE"); - const auto RUNTIMEdir = getenv("XDG_RUNTIME_DIR"); - const std::string USERID = std::to_string(getpwuid(getuid())->pw_uid); + const auto HISenv = getenv("HYPRLAND_INSTANCE_SIGNATURE"); + const auto RUNTIMEdir = getenv("XDG_RUNTIME_DIR"); + const std::string USERID = std::to_string(getpwuid(getuid())->pw_uid); - const auto USERDIR = RUNTIMEdir ? RUNTIMEdir + std::string{"/hypr/"} : "/run/user/" + USERID + "/hypr/"; + const auto USERDIR = RUNTIMEdir ? RUNTIMEdir + std::string{"/hypr/"} : "/run/user/" + USERID + "/hypr/"; - std::string socketPath = HISenv ? USERDIR + std::string(HISenv) + "/.hyprpaper.sock" : USERDIR + ".hyprpaper.sock"; + std::string socketPath = HISenv ? USERDIR + std::string(HISenv) + "/.hyprpaper.sock" : USERDIR + ".hyprpaper.sock"; if (!HISenv) mkdir(USERDIR.c_str(), S_IRWXU); @@ -45,9 +46,9 @@ void CIPCSocket::initialize() { listen(SOCKET, 10); sockaddr_in clientAddress = {}; - socklen_t clientSize = sizeof(clientAddress); + socklen_t clientSize = sizeof(clientAddress); - char readBuffer[1024] = {0}; + char readBuffer[1024] = {0}; Debug::log(LOG, "hyprpaper socket started at %s (fd: %i)", socketPath.c_str(), SOCKET); while (1) { @@ -60,13 +61,13 @@ void CIPCSocket::initialize() { Debug::log(LOG, "Accepted incoming socket connection request on fd %i", ACCEPTEDCONNECTION); std::lock_guard lg(g_pHyprpaper->m_mtTickMutex); - auto messageSize = read(ACCEPTEDCONNECTION, readBuffer, 1024); + auto messageSize = read(ACCEPTEDCONNECTION, readBuffer, 1024); readBuffer[messageSize == 1024 ? 1023 : messageSize] = '\0'; if (messageSize == 0) break; std::string request(readBuffer); - m_szRequest = request; + m_szRequest = request; m_bRequestReady = true; g_pHyprpaper->tick(true); @@ -75,7 +76,7 @@ void CIPCSocket::initialize() { } write(ACCEPTEDCONNECTION, m_szReply.c_str(), m_szReply.length()); m_bReplyReady = false; - m_szReply = ""; + m_szReply = ""; } while (1); Debug::log(LOG, "Closing Accepted Connection"); @@ -102,8 +103,8 @@ bool CIPCSocket::mainThreadParseRequest() { Debug::log(LOG, "Received a request: %s", copy.c_str()); // set default reply - m_szReply = "ok"; - m_bReplyReady = true; + m_szReply = "ok"; + m_bReplyReady = true; m_bRequestReady = false; // config commands @@ -129,7 +130,7 @@ bool CIPCSocket::mainThreadParseRequest() { return false; } - m_szReply = ""; + m_szReply = ""; long unsigned int i = 0; for (auto& [name, target] : g_pHyprpaper->m_mWallpaperTargets) { m_szReply += name; @@ -151,7 +152,7 @@ bool CIPCSocket::mainThreadParseRequest() { return false; } - m_szReply = ""; + m_szReply = ""; long unsigned int i = 0; for (auto& [mon, path1] : g_pHyprpaper->m_mMonitorActiveWallpapers) { m_szReply += mon + " = " + path1; diff --git a/src/ipc/Socket.hpp b/src/ipc/Socket.hpp index a616455..1e064da 100644 --- a/src/ipc/Socket.hpp +++ b/src/ipc/Socket.hpp @@ -4,20 +4,18 @@ #include class CIPCSocket { -public: - void initialize(); + public: + void initialize(); - bool mainThreadParseRequest(); + bool mainThreadParseRequest(); -private: - - std::mutex m_mtRequestMutex; + private: + std::mutex m_mtRequestMutex; std::string m_szRequest = ""; - std::string m_szReply = ""; + std::string m_szReply = ""; bool m_bRequestReady = false; - bool m_bReplyReady = false; - + bool m_bReplyReady = false; }; inline std::unique_ptr g_pIPCSocket; \ No newline at end of file diff --git a/src/main.cpp b/src/main.cpp index 67e38b2..d833364 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -7,7 +7,7 @@ int main(int argc, char** argv, char** envp) { // parse some args std::string configPath; - bool noFractional = false; + bool noFractional = false; for (int i = 1; i < argc; ++i) { if ((!strcmp(argv[i], "-c") || !strcmp(argv[i], "--config")) && argc >= i + 2) { configPath = std::string(argv[++i]); @@ -16,18 +16,18 @@ int main(int argc, char** argv, char** envp) { noFractional = true; Debug::log(LOG, "Disabling fractional scaling support!"); } else { - std::cout << "Hyprpaper usage: hyprpaper [arg [...]].\n\nArguments:\n" << - "--help -h | Show this help message\n" << - "--config -c | Specify config file to use\n" << - "--no-fractional -n | Disable fractional scaling support\n"; + std::cout << "Hyprpaper usage: hyprpaper [arg [...]].\n\nArguments:\n" + << "--help -h | Show this help message\n" + << "--config -c | Specify config file to use\n" + << "--no-fractional -n | Disable fractional scaling support\n"; return 1; } } // starts - g_pHyprpaper = std::make_unique(); + g_pHyprpaper = std::make_unique(); g_pHyprpaper->m_szExplicitConfigPath = configPath; - g_pHyprpaper->m_bNoFractionalScale = noFractional; + g_pHyprpaper->m_bNoFractionalScale = noFractional; g_pHyprpaper->init(); return 0; diff --git a/src/render/LayerSurface.cpp b/src/render/LayerSurface.cpp index cd0b21a..9122e1a 100644 --- a/src/render/LayerSurface.cpp +++ b/src/render/LayerSurface.cpp @@ -5,62 +5,92 @@ CLayerSurface::CLayerSurface(SMonitor* pMonitor) { m_pMonitor = pMonitor; - pSurface = wl_compositor_create_surface(g_pHyprpaper->m_sCompositor); - pCursorSurface = wl_compositor_create_surface(g_pHyprpaper->m_sCompositor); + pSurface = makeShared(g_pHyprpaper->m_pCompositor->sendCreateSurface()); if (!pSurface) { Debug::log(CRIT, "The compositor did not allow hyprpaper a surface!"); exit(1); } - const auto PINPUTREGION = wl_compositor_create_region(g_pHyprpaper->m_sCompositor); + const auto PINPUTREGION = makeShared(g_pHyprpaper->m_pCompositor->sendCreateRegion()); if (!PINPUTREGION) { Debug::log(CRIT, "The compositor did not allow hyprpaper a region!"); exit(1); } - wl_surface_set_input_region(pSurface, PINPUTREGION); + pSurface->sendSetInputRegion(PINPUTREGION.get()); - pLayerSurface = zwlr_layer_shell_v1_get_layer_surface(g_pHyprpaper->m_sLayerShell, pSurface, pMonitor->output, ZWLR_LAYER_SHELL_V1_LAYER_BACKGROUND, "hyprpaper"); + pLayerSurface = makeShared( + g_pHyprpaper->m_pLayerShell->sendGetLayerSurface(pSurface->resource(), pMonitor->output->resource(), ZWLR_LAYER_SHELL_V1_LAYER_BACKGROUND, "hyprpaper")); if (!pLayerSurface) { Debug::log(CRIT, "The compositor did not allow hyprpaper a layersurface!"); exit(1); } - zwlr_layer_surface_v1_set_size(pLayerSurface, 0, 0); - zwlr_layer_surface_v1_set_anchor(pLayerSurface, ZWLR_LAYER_SURFACE_V1_ANCHOR_TOP | ZWLR_LAYER_SURFACE_V1_ANCHOR_RIGHT | ZWLR_LAYER_SURFACE_V1_ANCHOR_BOTTOM | ZWLR_LAYER_SURFACE_V1_ANCHOR_LEFT); - zwlr_layer_surface_v1_set_exclusive_zone(pLayerSurface, -1); - zwlr_layer_surface_v1_add_listener(pLayerSurface, &Events::layersurfaceListener, this); - wl_surface_commit(pSurface); + pLayerSurface->sendSetSize(0, 0); + pLayerSurface->sendSetAnchor((zwlrLayerSurfaceV1Anchor)(ZWLR_LAYER_SURFACE_V1_ANCHOR_TOP | ZWLR_LAYER_SURFACE_V1_ANCHOR_RIGHT | ZWLR_LAYER_SURFACE_V1_ANCHOR_BOTTOM | + ZWLR_LAYER_SURFACE_V1_ANCHOR_LEFT)); + pLayerSurface->sendSetExclusiveZone(-1); - wl_region_destroy(PINPUTREGION); + pLayerSurface->setConfigure([this](CCZwlrLayerSurfaceV1* r, uint32_t serial, uint32_t x, uint32_t y) { + m_pMonitor->size = Vector2D((double)x, (double)y); + m_pMonitor->wantsReload = true; + m_pMonitor->configureSerial = serial; + m_pMonitor->wantsACK = true; + m_pMonitor->initialized = true; + + Debug::log(LOG, "configure for %s", m_pMonitor->name.c_str()); + }); + + pLayerSurface->setClosed([this](CCZwlrLayerSurfaceV1* r) { + for (auto& m : g_pHyprpaper->m_vMonitors) { + std::erase_if(m->layerSurfaces, [&](const auto& other) { return other.get() == this; }); + if (m->pCurrentLayerSurface == this) { + if (m->layerSurfaces.empty()) { + m->pCurrentLayerSurface = nullptr; + } else { + m->pCurrentLayerSurface = m->layerSurfaces.begin()->get(); + g_pHyprpaper->recheckMonitor(m.get()); + } + } + } + }); + + pSurface->sendCommit(); // fractional scale, if supported by the compositor - if (g_pHyprpaper->m_sFractionalScale) { - pFractionalScaleInfo = wp_fractional_scale_manager_v1_get_fractional_scale(g_pHyprpaper->m_sFractionalScale, pSurface); - wp_fractional_scale_v1_add_listener(pFractionalScaleInfo, &Events::scaleListener, this); - pViewport = wp_viewporter_get_viewport(g_pHyprpaper->m_sViewporter, pSurface); - wl_surface_commit(pSurface); - } + if (g_pHyprpaper->m_pFractionalScale && g_pHyprpaper->m_pViewporter) { + pFractionalScaleInfo = makeShared(g_pHyprpaper->m_pFractionalScale->sendGetFractionalScale(pSurface->resource())); + pFractionalScaleInfo->setPreferredScale([this](CCWpFractionalScaleV1* r, uint32_t sc120) { + const double SCALE = sc120 / 120.0; + + Debug::log(LOG, "handlePreferredScale: %.2lf for %lx", SCALE, this); + + if (fScale != SCALE) { + fScale = SCALE; + std::lock_guard lg(g_pHyprpaper->m_mtTickMutex); + m_pMonitor->wantsReload = true; + g_pHyprpaper->tick(true); + } + }); + + pViewport = makeShared(g_pHyprpaper->m_pViewporter->sendGetViewport(pSurface->resource())); + + pSurface->sendCommit(); + } else + Debug::log(ERR, "No fractional-scale-v1 / wp-viewporter support from the compositor! fractional scaling will not work."); wl_display_flush(g_pHyprpaper->m_sDisplay); } CLayerSurface::~CLayerSurface() { - - if (pCursorTheme) - wl_cursor_theme_destroy(pCursorTheme); - - if (g_pHyprpaper->m_sFractionalScale && pFractionalScaleInfo) { - wp_fractional_scale_v1_destroy(pFractionalScaleInfo); - - wp_viewport_destroy(pViewport); - } - - zwlr_layer_surface_v1_destroy(pLayerSurface); - wl_surface_destroy(pSurface); + // hyprwayland-scanner will send the destructors automatically. Neat. + pLayerSurface.reset(); + pFractionalScaleInfo.reset(); + pViewport.reset(); + pSurface.reset(); wl_display_flush(g_pHyprpaper->m_sDisplay); } diff --git a/src/render/LayerSurface.hpp b/src/render/LayerSurface.hpp index 151a8bf..73127fb 100644 --- a/src/render/LayerSurface.hpp +++ b/src/render/LayerSurface.hpp @@ -1,24 +1,23 @@ #pragma once #include "../defines.hpp" +#include "protocols/fractional-scale-v1.hpp" +#include "protocols/viewporter.hpp" +#include "protocols/wayland.hpp" +#include "protocols/wlr-layer-shell-unstable-v1.hpp" struct SMonitor; class CLayerSurface { -public: + public: explicit CLayerSurface(SMonitor*); ~CLayerSurface(); - SMonitor* m_pMonitor = nullptr; + SMonitor* m_pMonitor = nullptr; - zwlr_layer_surface_v1* pLayerSurface = nullptr; - wl_surface* pSurface = nullptr; - - wl_cursor_theme* pCursorTheme = nullptr; - wl_cursor_image* pCursorImg = nullptr; - wl_surface* pCursorSurface = nullptr; - - wp_fractional_scale_v1* pFractionalScaleInfo = nullptr; - wp_viewport* pViewport = nullptr; - double fScale = 1.0; + SP pLayerSurface = nullptr; + SP pSurface = nullptr; + SP pFractionalScaleInfo = nullptr; + SP pViewport = nullptr; + double fScale = 1.0; }; diff --git a/src/render/WallpaperTarget.cpp b/src/render/WallpaperTarget.cpp index b49d354..6c2ab3b 100644 --- a/src/render/WallpaperTarget.cpp +++ b/src/render/WallpaperTarget.cpp @@ -1,5 +1,6 @@ #include "WallpaperTarget.hpp" +#include #include CWallpaperTarget::~CWallpaperTarget() { @@ -9,36 +10,36 @@ CWallpaperTarget::~CWallpaperTarget() { void CWallpaperTarget::create(const std::string& path) { m_szPath = path; - const auto BEGINLOAD = std::chrono::system_clock::now(); + const auto BEGINLOAD = std::chrono::system_clock::now(); cairo_surface_t* CAIROSURFACE = nullptr; - const auto len = path.length(); + const auto len = path.length(); if (path.find(".png") == len - 4 || path.find(".PNG") == len - 4) { CAIROSURFACE = cairo_image_surface_create_from_png(path.c_str()); } else if (path.find(".jpg") == len - 4 || path.find(".JPG") == len - 4 || path.find(".jpeg") == len - 5 || path.find(".JPEG") == len - 5) { CAIROSURFACE = JPEG::createSurfaceFromJPEG(path); - m_bHasAlpha = false; + m_bHasAlpha = false; } else if (path.find(".bmp") == len - 4 || path.find(".BMP") == len - 4) { CAIROSURFACE = BMP::createSurfaceFromBMP(path); - m_bHasAlpha = false; + m_bHasAlpha = false; } else if (path.find(".webp") == len - 5 || path.find(".WEBP") == len - 5) { CAIROSURFACE = WEBP::createSurfaceFromWEBP(path); } else { // magic is slow, so only use it when no recognized extension is found - auto handle = magic_open(MAGIC_NONE|MAGIC_COMPRESS); + auto handle = magic_open(MAGIC_NONE | MAGIC_COMPRESS); magic_load(handle, nullptr); - const auto type_str = std::string(magic_file(handle, path.c_str())); + const auto type_str = std::string(magic_file(handle, path.c_str())); const auto first_word = type_str.substr(0, type_str.find(" ")); if (first_word == "PNG") { CAIROSURFACE = cairo_image_surface_create_from_png(path.c_str()); } else if (first_word == "JPEG") { CAIROSURFACE = JPEG::createSurfaceFromJPEG(path); - m_bHasAlpha = false; + m_bHasAlpha = false; } else if (first_word == "BMP") { CAIROSURFACE = BMP::createSurfaceFromBMP(path); - m_bHasAlpha = false; + m_bHasAlpha = false; } else { Debug::log(CRIT, "unrecognized image %s", path.c_str()); exit(1); @@ -50,7 +51,7 @@ void CWallpaperTarget::create(const std::string& path) { exit(1); } - m_vSize = { cairo_image_surface_get_width(CAIROSURFACE), cairo_image_surface_get_height(CAIROSURFACE) }; + m_vSize = {cairo_image_surface_get_width(CAIROSURFACE), cairo_image_surface_get_height(CAIROSURFACE)}; const auto MS = std::chrono::duration_cast(std::chrono::system_clock::now() - BEGINLOAD).count() / 1000.f; diff --git a/src/render/WallpaperTarget.hpp b/src/render/WallpaperTarget.hpp index 5a7eea6..9a28d92 100644 --- a/src/render/WallpaperTarget.hpp +++ b/src/render/WallpaperTarget.hpp @@ -6,17 +6,16 @@ #include "../helpers/Webp.hpp" class CWallpaperTarget { -public: - + public: ~CWallpaperTarget(); - void create(const std::string& path); + void create(const std::string& path); - std::string m_szPath; + std::string m_szPath; - Vector2D m_vSize; + Vector2D m_vSize; - bool m_bHasAlpha = true; + bool m_bHasAlpha = true; cairo_surface_t* m_pCairoSurface; };