diff --git a/CMakeLists.txt b/CMakeLists.txt index 348ae14..2eb402c 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -29,7 +29,7 @@ pkg_check_modules( libinput>=1.26.0 wayland-client wayland-protocols - hyprutils>=0.2.3 + hyprutils>=0.5.2 pixman-1 libdrm gbm @@ -137,6 +137,14 @@ add_test( COMMAND simpleWindow "simpleWindow") add_dependencies(tests simpleWindow) +add_executable(attachments "tests/Attachments.cpp") +target_link_libraries(attachments PRIVATE PkgConfig::deps aquamarine) +add_test( + NAME "attachments" + WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}/tests + COMMAND attachments "attachments") +add_dependencies(tests attachments) + # Installation install(TARGETS aquamarine) install(DIRECTORY "include/aquamarine" DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}) diff --git a/flake.lock b/flake.lock index 3aff9c4..fba0969 100644 --- a/flake.lock +++ b/flake.lock @@ -10,11 +10,11 @@ ] }, "locked": { - "lastModified": 1737978343, - "narHash": "sha256-TfFS0HCEJh63Kahrkp1h9hVDMdLU8a37Zz+IFucxyfA=", + "lastModified": 1741534688, + "narHash": "sha256-EV3945SnjOCuRVbGRghsWx/9D89FyshnSO1Q6/TuQ14=", "owner": "hyprwm", "repo": "hyprutils", - "rev": "6a8bc9d2a4451df12f5179dc0b1d2d46518a90ab", + "rev": "dd1f720cbc2dbb3c71167c9598045dd3261d27b3", "type": "github" }, "original": { @@ -33,11 +33,11 @@ ] }, "locked": { - "lastModified": 1735493474, - "narHash": "sha256-fktzv4NaqKm94VAkAoVqO/nqQlw+X0/tJJNAeCSfzK4=", + "lastModified": 1739870480, + "narHash": "sha256-SiDN5BGxa/1hAsqhgJsS03C3t2QrLgBT8u+ENJ0Qzwc=", "owner": "hyprwm", "repo": "hyprwayland-scanner", - "rev": "de913476b59ee88685fdc018e77b8f6637a2ae0b", + "rev": "206367a08dc5ac4ba7ad31bdca391d098082e64b", "type": "github" }, "original": { @@ -48,11 +48,11 @@ }, "nixpkgs": { "locked": { - "lastModified": 1737885589, - "narHash": "sha256-Zf0hSrtzaM1DEz8//+Xs51k/wdSajticVrATqDrfQjg=", + "lastModified": 1741379970, + "narHash": "sha256-Wh7esNh7G24qYleLvgOSY/7HlDUzWaL/n4qzlBePpiw=", "owner": "NixOS", "repo": "nixpkgs", - "rev": "852ff1d9e153d8875a83602e03fdef8a63f0ecf8", + "rev": "36fd87baa9083f34f7f5027900b62ee6d09b1f2f", "type": "github" }, "original": { diff --git a/include/aquamarine/misc/Attachment.hpp b/include/aquamarine/misc/Attachment.hpp index f44343d..f51865a 100644 --- a/include/aquamarine/misc/Attachment.hpp +++ b/include/aquamarine/misc/Attachment.hpp @@ -33,7 +33,7 @@ namespace Aquamarine { // Reinterpret SP into SP. // This is safe because we looked up this attachment by typeid(T), // so it must be an SP. - return *reinterpret_cast*>(&it->second); + return Hyprutils::Memory::reinterpretPointerCast(it->second); } // Also removes the previous attachment of the same type if one exists void add(Hyprutils::Memory::CSharedPointer attachment); diff --git a/src/misc/Attachment.cpp b/src/misc/Attachment.cpp index fcfbede..33db180 100644 --- a/src/misc/Attachment.cpp +++ b/src/misc/Attachment.cpp @@ -12,7 +12,7 @@ void Aquamarine::CAttachmentManager::add(SP attachment) { void Aquamarine::CAttachmentManager::remove(SP attachment) { const IAttachment& att = *attachment; auto it = attachments.find(typeid(att)); - if (it != attachments.end()) + if (it != attachments.end() && it->second == attachment) attachments.erase(it); } diff --git a/tests/Attachments.cpp b/tests/Attachments.cpp new file mode 100644 index 0000000..7aa6829 --- /dev/null +++ b/tests/Attachments.cpp @@ -0,0 +1,64 @@ +#include +#include +#include +#include "shared.hpp" + +class CFooAttachment : public Aquamarine::IAttachment { + public: + int counter = 0; +}; + +class CBarAttachment : public Aquamarine::IAttachment { + public: + int counter = 0; +}; + +int main() { + Aquamarine::CAttachmentManager attachments; + int ret = 0; + EXPECT(attachments.has(), false); + EXPECT(attachments.get(), nullptr); + EXPECT(attachments.has(), false); + EXPECT(attachments.get(), nullptr); + + auto foo = Hyprutils::Memory::makeShared(); + attachments.add(foo); + EXPECT(attachments.has(), true); + EXPECT(attachments.has(), false); + foo->counter++; + EXPECT(attachments.get(), foo); + EXPECT(attachments.get()->counter, 1); + + attachments.add(Hyprutils::Memory::makeShared()); + EXPECT(attachments.get()->counter, 1); + EXPECT(attachments.get()->counter, 0); + + Hyprutils::Memory::CWeakPointer bar = attachments.get(); + EXPECT(bar.valid(), true); + bar->counter = 5; + + // test overriding an attachment + attachments.add(Hyprutils::Memory::makeShared()); + Hyprutils::Memory::CWeakPointer newBar = attachments.get(); + EXPECT(bar == newBar, false); + EXPECT(attachments.get()->counter, 0); + + // should be a noop as this is a different attachment + attachments.remove(Hyprutils::Memory::makeShared()); + EXPECT(attachments.has(), true); + EXPECT(attachments.has(), true); + + attachments.remove(foo); + EXPECT(attachments.has(), false); + EXPECT(attachments.has(), true); + + attachments.removeByType(); + EXPECT(attachments.has(), false); + EXPECT(attachments.has(), false); + + EXPECT(foo.strongRef(), 1); + EXPECT(bar.valid(), false); + EXPECT(newBar.valid(), false); + + return ret; +} diff --git a/tests/shared.hpp b/tests/shared.hpp new file mode 100644 index 0000000..81b7c8c --- /dev/null +++ b/tests/shared.hpp @@ -0,0 +1,20 @@ +#pragma once +#include + +namespace Colors { + constexpr const char* RED = "\x1b[31m"; + constexpr const char* GREEN = "\x1b[32m"; + constexpr const char* YELLOW = "\x1b[33m"; + constexpr const char* BLUE = "\x1b[34m"; + constexpr const char* MAGENTA = "\x1b[35m"; + constexpr const char* CYAN = "\x1b[36m"; + constexpr const char* RESET = "\x1b[0m"; +}; + +#define EXPECT(expr, val) \ + if (const auto RESULT = expr; RESULT != (val)) { \ + std::cout << Colors::RED << "Failed: " << Colors::RESET << #expr << ", expected " << val << " but got " << RESULT << "\n"; \ + ret = 1; \ + } else { \ + std::cout << Colors::GREEN << "Passed " << Colors::RESET << #expr << ". Got " << val << "\n"; \ + }