From 3d1d344ec1bb39b7323c01eb831c117a686b39f3 Mon Sep 17 00:00:00 2001 From: pupbrained Date: Tue, 13 May 2025 01:48:08 -0400 Subject: [PATCH] meow --- .clang-format | 18 ++- include/argparse.hpp | 102 ++++++------- include/matchit.hpp | 8 +- src/Config/Config.hpp | 8 +- src/Core/SystemData.cpp | 5 +- src/Core/SystemData.hpp | 1 + src/OS/Linux.cpp | 68 ++++----- src/Services/Weather/IWeatherService.hpp | 1 + src/UI/UI.cpp | 3 +- src/UI/UI.hpp | 4 +- src/Wrappers/DBus.hpp | 182 ++++++++++++++++++----- src/Wrappers/Wayland.hpp | 97 ++++++++++-- src/Wrappers/XCB.hpp | 77 +++++----- src/main.cpp | 5 +- 14 files changed, 383 insertions(+), 196 deletions(-) diff --git a/.clang-format b/.clang-format index 09cb3cf..98218d0 100644 --- a/.clang-format +++ b/.clang-format @@ -23,16 +23,22 @@ ContinuationIndentWidth: 2 Cpp11BracedListStyle: false IncludeBlocks: Regroup IncludeCategories: - # 1. System headers (, , etc.) - Regex: '^<.*>$' Priority: 1 - # 2. Project headers starting with "src/" - - Regex: '^"src/.*"' + - Regex: '^"Config/.*"' Priority: 2 - # 3. All other quoted headers (including same-directory like "system_data.h") - # This acts as a fallback for quoted includes not matching the above. - - Regex: '^".*"' + - Regex: '^"Core/.*"' Priority: 3 + - Regex: '^"Services/.*"' + Priority: 4 + - Regex: '^"UI/.*"' + Priority: 5 + - Regex: '^"Util/.*"' + Priority: 6 + - Regex: '^"Wrappers/.*"' + Priority: 7 + - Regex: '^".*"$' + Priority: 8 IndentExternBlock: Indent IndentPPDirectives: BeforeHash NamespaceIndentation: All diff --git a/include/argparse.hpp b/include/argparse.hpp index 3696f62..475de03 100644 --- a/include/argparse.hpp +++ b/include/argparse.hpp @@ -1005,48 +1005,46 @@ namespace argparse { */ template fn action(F&& callable, Args&&... bound_args) - -> Argument& - requires(std::is_invocable_v) - { - using RawReturnType = std::invoke_result_t; + -> Argument& requires(std::is_invocable_v) { + using RawReturnType = std::invoke_result_t; - if constexpr (std::is_void_v) { - m_actions.emplace_back( - [f = std::forward(callable), tup = std::make_tuple(std::forward(bound_args)...)](const String& opt) mutable -> Result<> { - details::apply_plus_one(f, tup, opt); - return {}; - } - ); - } else if constexpr (argparse::details::is_specialization_v && std::is_void_v) { - m_actions.emplace_back( - [f = std::forward(callable), tup = std::make_tuple(std::forward(bound_args)...)](const String& opt) mutable -> Result<> { - return details::apply_plus_one(f, tup, opt); - } - ); - } else if constexpr (argparse::details::is_specialization_v) { - m_actions.emplace_back( - [f = std::forward(callable), tup = std::make_tuple(std::forward(bound_args)...)](const String& opt) mutable -> Result { - RawReturnType result = details::apply_plus_one(f, tup, opt); - if (result) { - if constexpr (!std::is_void_v) { - return result.value(); - } else { - return ArgValue {}; - } - } else { - return Err(result.error()); + if constexpr (std::is_void_v) { + m_actions.emplace_back( + [f = std::forward(callable), tup = std::make_tuple(std::forward(bound_args)...)](const String& opt) mutable -> Result<> { + details::apply_plus_one(f, tup, opt); + return {}; } - } - ); - } else { - m_actions.emplace_back( - [f = std::forward(callable), tup = std::make_tuple(std::forward(bound_args)...)](const String& opt) mutable -> Result { - return details::apply_plus_one(f, tup, opt); - } - ); + ); + } else if constexpr (argparse::details::is_specialization_v && std::is_void_v) { + m_actions.emplace_back( + [f = std::forward(callable), tup = std::make_tuple(std::forward(bound_args)...)](const String& opt) mutable -> Result<> { + return details::apply_plus_one(f, tup, opt); + } + ); + } else if constexpr (argparse::details::is_specialization_v) { + m_actions.emplace_back( + [f = std::forward(callable), tup = std::make_tuple(std::forward(bound_args)...)](const String& opt) mutable -> Result { + RawReturnType result = details::apply_plus_one(f, tup, opt); + if (result) { + if constexpr (!std::is_void_v) { + return result.value(); + } else { + return ArgValue {}; + } + } else { + return Err(result.error()); + } + } + ); + } else { + m_actions.emplace_back( + [f = std::forward(callable), tup = std::make_tuple(std::forward(bound_args)...)](const String& opt) mutable -> Result { + return details::apply_plus_one(f, tup, opt); + } + ); + } + return *this; } - return *this; - } /** * @brief Store the argument value into a boolean variable @@ -1055,7 +1053,7 @@ namespace argparse { * @details If no default or implicit value is set, configures the argument as a flag */ fn store_into(bool& var) - -> Argument& { + ->Argument& { if ((!m_default_value.has_value()) && (!m_implicit_value.has_value())) flag(); @@ -1077,9 +1075,7 @@ namespace argparse { * @return Reference to this argument for method chaining */ template - fn store_into(T& var) -> Argument& - requires(std::is_integral_v) - { + fn store_into(T& var) -> Argument& requires(std::is_integral_v) { if (m_default_value.has_value()) var = std::get(m_default_value.value()); @@ -1103,9 +1099,7 @@ namespace argparse { * @return Reference to this argument for method chaining */ template - fn store_into(T& var) -> Argument& - requires(std::is_floating_point_v) - { + fn store_into(T& var)->Argument& requires(std::is_floating_point_v) { if (m_default_value.has_value()) var = std::get(m_default_value.value()); @@ -1128,7 +1122,7 @@ namespace argparse { * @return Reference to this argument for method chaining */ fn store_into(String& var) - -> Argument& { + ->Argument& { if (m_default_value.has_value()) var = std::get(m_default_value.value()); @@ -1291,9 +1285,7 @@ namespace argparse { * - 'g'/'G': General format */ template - fn scan() -> Argument& - requires(std::is_arithmetic_v) - { + fn scan() -> Argument& requires(std::is_arithmetic_v) { static_assert(!(std::is_const_v || std::is_volatile_v), "T should not be cv-qualified"); fn is_one_of = [](char c, auto... x) constexpr { @@ -1382,7 +1374,7 @@ namespace argparse { * @return Reference to this argument for method chaining */ fn nargs(const usize num_args) - -> Argument& { + ->Argument& { m_num_args_range = NArgsRange { num_args, num_args }; return *this; } @@ -1574,8 +1566,7 @@ namespace argparse { if (m_implicit_value.has_value()) m_values.emplace_back(*m_implicit_value); - for (usize i = 0; i < m_actions.size(); ++i) { - auto& action = m_actions[i]; + for (auto& action : m_actions) { Result<> action_call_result; std::visit([&](auto& f) { if constexpr (std::is_same_v>) { @@ -1658,8 +1649,7 @@ namespace argparse { }; if (!dry_run) { - for (usize i = 0; i < m_actions.size(); ++i) { - auto& action = m_actions[i]; + for (auto& action : m_actions) { Result<> apply_result = std::visit(ActionApply { start, end, *this }, action); if (!apply_result) return Err(apply_result.error()); @@ -2117,7 +2107,7 @@ namespace argparse { }; fn consume_digits = [=](StringView sd) -> StringView { - const auto it = std::ranges::find_if_not(sd, is_digit); + const auto* const it = std::ranges::find_if_not(sd, is_digit); return sd.substr(static_cast(it - std::begin(sd))); }; diff --git a/include/matchit.hpp b/include/matchit.hpp index bc60415..8979347 100644 --- a/include/matchit.hpp +++ b/include/matchit.hpp @@ -729,7 +729,8 @@ namespace matchit { template class App { public: - constexpr App(Unary&& unary, const Pattern& pattern) : mUnary { std::move(unary) }, mPattern { pattern } {} + constexpr App(Unary&& unary, const Pattern& pattern) + : mUnary { std::move(unary) }, mPattern { pattern } {} [[nodiscard]] constexpr fn unary() const -> const Unary& { return mUnary; @@ -1086,7 +1087,8 @@ namespace matchit { public: constexpr Id() = default; - constexpr Id(const Id& id) : mBlock(BlockVT { &id.block() }) {} + constexpr Id(const Id& id) + : mBlock(BlockVT { &id.block() }) {} // non-const to inform users not to mark Id as const. template @@ -1790,4 +1792,4 @@ namespace matchit { using impl::SubrangeT; using impl::when; } // namespace matchit -// NOLINTEND(readability-identifier-*, cppcoreguidelines-special-member-functions) \ No newline at end of file +// NOLINTEND(readability-identifier-*, cppcoreguidelines-special-member-functions) diff --git a/src/Config/Config.hpp b/src/Config/Config.hpp index 4c400f9..d41569c 100644 --- a/src/Config/Config.hpp +++ b/src/Config/Config.hpp @@ -15,15 +15,17 @@ #include "Util/Env.hpp" #endif -#include "../Services/Weather/MetNoService.hpp" -#include "../Services/Weather/OpenMeteoService.hpp" -#include "../Services/Weather/OpenWeatherMapService.hpp" #include "Services/Weather.hpp" + #include "Util/Definitions.hpp" #include "Util/Error.hpp" #include "Util/Logging.hpp" #include "Util/Types.hpp" +#include "../Services/Weather/MetNoService.hpp" +#include "../Services/Weather/OpenMeteoService.hpp" +#include "../Services/Weather/OpenWeatherMapService.hpp" + using util::error::DracError; using util::types::CStr, util::types::String, util::types::Array, util::types::Option, util::types::Result; diff --git a/src/Core/SystemData.cpp b/src/Core/SystemData.cpp index aabb22e..02487a8 100644 --- a/src/Core/SystemData.cpp +++ b/src/Core/SystemData.cpp @@ -7,13 +7,16 @@ #include // matchit::{match, is, in, _} #include "Config/Config.hpp" -#include "OS/OperatingSystem.hpp" + #include "Services/PackageCounting.hpp" #include "Services/Weather.hpp" + #include "Util/Definitions.hpp" #include "Util/Error.hpp" #include "Util/Types.hpp" +#include "OS/OperatingSystem.hpp" + using util::error::DracError, util::error::DracErrorCode; namespace { diff --git a/src/Core/SystemData.hpp b/src/Core/SystemData.hpp index d7ae4ec..cee6efe 100644 --- a/src/Core/SystemData.hpp +++ b/src/Core/SystemData.hpp @@ -3,6 +3,7 @@ #include // std::{formatter, format_to} #include "Services/Weather.hpp" + #include "Util/Definitions.hpp" #include "Util/Error.hpp" #include "Util/Types.hpp" diff --git a/src/OS/Linux.cpp b/src/OS/Linux.cpp index 28b11d0..b296473 100644 --- a/src/OS/Linux.cpp +++ b/src/OS/Linux.cpp @@ -1,32 +1,34 @@ #ifdef __linux__ // clang-format off -#include // PATH_MAX -#include // std::strlen -#include // std::{unexpected, expected} -#include // std::filesystem::{current_path, directory_entry, directory_iterator, etc.} -#include // std::{format, format_to_n} -#include // std::ifstream -#include // glz::read_beve -#include // glz::write_beve -#include // std::numeric_limits -#include // matchit::{is, is_not, is_any, etc.} -#include // std::{getline, string (String)} -#include // std::string_view (StringView) -#include // ucred, getsockopt, SOL_SOCKET, SO_PEERCRED -#include // statvfs -#include // sysinfo -#include // utsname, uname -#include // readlink -#include // std::move +#include // PATH_MAX +#include // std::strlen +#include // std::{unexpected, expected} +#include // std::filesystem::{current_path, directory_entry, directory_iterator, etc.} +#include // std::{format, format_to_n} +#include // std::ifstream +#include // glz::read_beve +#include // glz::write_beve +#include // std::numeric_limits +#include // matchit::{is, is_not, is_any, etc.} +#include // std::{getline, string (String)} +#include // std::string_view (StringView) +#include // ucred, getsockopt, SOL_SOCKET, SO_PEERCRED +#include // statvfs +#include // sysinfo +#include // utsname, uname +#include // readlink +#include // std::move #include "Services/PackageCounting.hpp" + #include "Util/Caching.hpp" #include "Util/Definitions.hpp" #include "Util/Env.hpp" #include "Util/Error.hpp" #include "Util/Logging.hpp" #include "Util/Types.hpp" + #include "Wrappers/DBus.hpp" #include "Wrappers/Wayland.hpp" #include "Wrappers/XCB.hpp" @@ -40,7 +42,7 @@ using util::types::String, util::types::Result, util::types::Err, util::types::u namespace { #ifdef HAVE_XCB fn GetX11WindowManager() -> Result { - using namespace xcb; + using namespace XCB; using namespace matchit; using enum ConnError; using util::types::StringView; @@ -65,10 +67,10 @@ namespace { ) ); - fn internAtom = [&conn](const StringView name) -> Result { + fn internAtom = [&conn](const StringView name) -> Result { using util::types::u16; - const ReplyGuard reply(InternAtomReply(conn.get(), InternAtom(conn.get(), 0, static_cast(name.size()), name.data()), nullptr)); + const ReplyGuard reply(InternAtomReply(conn.get(), InternAtom(conn.get(), 0, static_cast(name.size()), name.data()), nullptr)); if (!reply) return Err(DracError(DracErrorCode::PlatformSpecific, std::format("Failed to get X11 atom reply for '{}'", name))); @@ -76,9 +78,9 @@ namespace { return reply->atom; }; - const Result supportingWmCheckAtom = internAtom("_NET_SUPPORTING_WM_CHECK"); - const Result wmNameAtom = internAtom("_NET_WM_NAME"); - const Result utf8StringAtom = internAtom("UTF8_STRING"); + const Result supportingWmCheckAtom = internAtom("_NET_SUPPORTING_WM_CHECK"); + const Result wmNameAtom = internAtom("_NET_WM_NAME"); + const Result utf8StringAtom = internAtom("UTF8_STRING"); if (!supportingWmCheckAtom || !wmNameAtom || !utf8StringAtom) { if (!supportingWmCheckAtom) @@ -93,7 +95,7 @@ namespace { return Err(DracError(DracErrorCode::PlatformSpecific, "Failed to get X11 atoms")); } - const ReplyGuard wmWindowReply(GetPropertyReply( + const ReplyGuard wmWindowReply(GetPropertyReply( conn.get(), GetProperty(conn.get(), 0, conn.rootScreen()->root, *supportingWmCheckAtom, ATOM_WINDOW, 0, 1), nullptr @@ -103,9 +105,9 @@ namespace { GetPropertyValueLength(wmWindowReply.get()) == 0) return Err(DracError(DracErrorCode::NotFound, "Failed to get _NET_SUPPORTING_WM_CHECK property")); - const window_t wmRootWindow = *static_cast(GetPropertyValue(wmWindowReply.get())); + const Window wmRootWindow = *static_cast(GetPropertyValue(wmWindowReply.get())); - const ReplyGuard wmNameReply(GetPropertyReply( + const ReplyGuard wmNameReply(GetPropertyReply( conn.get(), GetProperty(conn.get(), 0, wmRootWindow, *wmNameAtom, *utf8StringAtom, 0, 1024), nullptr )); @@ -127,7 +129,7 @@ namespace { fn GetWaylandCompositor() -> Result { using util::types::i32, util::types::Array, util::types::isize, util::types::StringView; - const wl::DisplayGuard display; + const Wayland::DisplayGuard display; if (!display) return Err(DracError(DracErrorCode::NotFound, "Failed to connect to display (is Wayland running?)")); @@ -226,9 +228,7 @@ namespace os { value = value.substr(1, value.length() - 2); if (value.empty()) - return Err( - DracError(DracErrorCode::ParseError, std::format("PRETTY_NAME value is empty or only quotes in /etc/os-release")) - ); + return Err(DracError(DracErrorCode::ParseError, std::format("PRETTY_NAME value is empty or only quotes in /etc/os-release"))); return value; } @@ -257,7 +257,7 @@ namespace os { fn GetNowPlaying() -> Result { #ifdef HAVE_DBUS - using namespace dbus; + using namespace DBus; Result connectionResult = Connection::busGet(DBUS_BUS_SESSION); if (!connectionResult) @@ -286,9 +286,7 @@ namespace os { MessageIter subIter = iter.recurse(); if (!subIter.isValid()) - return Err( - DracError(DracErrorCode::ParseError, "Invalid DBus ListNames reply format: Could not recurse into array") - ); + return Err(DracError(DracErrorCode::ParseError, "Invalid DBus ListNames reply format: Could not recurse into array")); while (subIter.getArgType() != DBUS_TYPE_INVALID) { if (Option name = subIter.getString()) diff --git a/src/Services/Weather/IWeatherService.hpp b/src/Services/Weather/IWeatherService.hpp index 250de61..807d1ed 100644 --- a/src/Services/Weather/IWeatherService.hpp +++ b/src/Services/Weather/IWeatherService.hpp @@ -1,6 +1,7 @@ #pragma once #include "Services/Weather.hpp" + #include "Util/Error.hpp" namespace weather { diff --git a/src/UI/UI.cpp b/src/UI/UI.cpp index 9db0317..aca789f 100644 --- a/src/UI/UI.cpp +++ b/src/UI/UI.cpp @@ -1,8 +1,9 @@ #include "UI.hpp" -#include "OS/OperatingSystem.hpp" #include "Util/Types.hpp" +#include "OS/OperatingSystem.hpp" + namespace ui { using namespace ftxui; using namespace util::types; diff --git a/src/UI/UI.hpp b/src/UI/UI.hpp index c0dec58..5e26669 100644 --- a/src/UI/UI.hpp +++ b/src/UI/UI.hpp @@ -3,8 +3,10 @@ #include // ftxui::Element #include // ftxui::Color -#include "Config/Config.hpp" #include "Core/SystemData.hpp" + +#include "Config/Config.hpp" + #include "Util/Types.hpp" namespace ui { diff --git a/src/Wrappers/DBus.hpp b/src/Wrappers/DBus.hpp index 3b8cb1d..08fb4ba 100644 --- a/src/Wrappers/DBus.hpp +++ b/src/Wrappers/DBus.hpp @@ -14,38 +14,64 @@ #include "Util/Types.hpp" // clang-format on -namespace dbus { +namespace DBus { using util::error::DracError, util::error::DracErrorCode; using util::types::Option, util::types::Result, util::types::Err, util::types::String, util::types::i32, util::types::u32, util::types::None; /** - * @brief RAII wrapper for DBusError. Automatically initializes and frees. + * @brief RAII wrapper for DBusError. Automatically initializes and frees the error. */ class Error { - DBusError m_err {}; - bool m_isInitialized = false; + DBusError m_err {}; ///< The D-Bus error object + bool m_isInitialized = false; ///< Flag indicating if the error is initialized public: + /** + * @brief Constructor + * + * Initializes the D-Bus error object. + */ Error() : m_isInitialized(true) { dbus_error_init(&m_err); } + /** + * @brief Destructor + * + * Frees the D-Bus error object if it was initialized. + */ ~Error() { if (m_isInitialized) dbus_error_free(&m_err); } + // Non-copyable Error(const Error&) = delete; fn operator=(const Error&)->Error& = delete; + /** + * @brief Move constructor + * + * Transfers ownership of the D-Bus error object. + * + * @param other The other Error object to move from + */ Error(Error&& other) noexcept : m_err(other.m_err), m_isInitialized(other.m_isInitialized) { other.m_isInitialized = false; dbus_error_init(&other.m_err); } + /** + * @brief Move assignment operator + * + * Transfers ownership of the D-Bus error object. + * + * @param other The other Error object to move from + * @return A reference to this object + */ fn operator=(Error&& other) noexcept -> Error& { if (this != &other) { if (m_isInitialized) @@ -61,8 +87,8 @@ namespace dbus { } /** - * @brief Checks if the D-Bus error is set. - * @return True if an error is set, false otherwise. + * @brief Checks if the error is set. + * @return True if the error is set and initialized, false otherwise. */ [[nodiscard]] fn isSet() const -> bool { return m_isInitialized && dbus_error_is_set(&m_err); @@ -91,6 +117,7 @@ namespace dbus { [[nodiscard]] fn get() -> DBusError* { return &m_err; } + /** * @brief Gets a const pointer to the underlying DBusError. * @return Const pointer to the DBusError struct. @@ -100,11 +127,11 @@ namespace dbus { } /** - * @brief Converts the D-Bus error to a DraconisError. - * @param code The DraconisError code to use if the D-Bus error is set. - * @return A DraconisError representing the D-Bus error, or an internal error if called when no D-Bus error is set. + * @brief Converts the D-Bus error to a DracError. + * @param code The DracErrorCode to use if the D-Bus error is set. + * @return A DracError representing the D-Bus error, or an internal error if called when no D-Bus error is set. */ - [[nodiscard]] fn toDraconisError(const DracErrorCode code = DracErrorCode::PlatformSpecific) const -> DracError { + [[nodiscard]] fn toDracError(const DracErrorCode code = DracErrorCode::PlatformSpecific) const -> DracError { if (isSet()) return { code, std::format("D-Bus Error: {} ({})", message(), name()) }; @@ -113,23 +140,36 @@ namespace dbus { }; /** - * @brief RAII wrapper for DBusMessageIter. Encapsulates iterator operations. - * Note: This wrapper does *not* own the message, only the iterator state. - * It's designed to be used within the scope where the MessageGuard is valid. + * @brief RAII wrapper for DBusMessageIter. Automatically frees the iterator. + * + * This class provides a convenient way to manage the lifetime of a D-Bus message iterator. */ class MessageIter { - DBusMessageIter m_iter {}; - bool m_isValid = false; - - explicit MessageIter(const DBusMessageIter& iter, const bool isValid) - : m_iter(iter), m_isValid(isValid) {} + DBusMessageIter m_iter {}; ///< The D-Bus message iterator + bool m_isValid = false; ///< Flag indicating if the iterator is valid + // Allows the Message class to access private members of this class. friend class Message; /** - * @brief Gets the value of a basic-typed argument. - * Unsafe: Caller must ensure 'value' points to memory suitable for the actual argument type. - * @param value Pointer to store the retrieved value. + * @brief Constructor + * + * Initializes the D-Bus message iterator. + * + * @param iter The D-Bus message iterator to wrap + * @param isValid Flag indicating if the iterator is valid + */ + explicit MessageIter(const DBusMessageIter& iter, const bool isValid) + : m_iter(iter), m_isValid(isValid) {} + + /** + * @brief Destructor + * + * Frees the D-Bus message iterator if it was initialized. + * + * @param value Pointer to the value to be freed + * + * @note This function is unsafe and should not be called directly. */ fn getBasic(void* value) -> void { if (m_isValid) @@ -137,11 +177,16 @@ namespace dbus { } public: + // Non-copyable MessageIter(const MessageIter&) = delete; fn operator=(const MessageIter&)->MessageIter& = delete; - MessageIter(MessageIter&&) = delete; - fn operator=(MessageIter&&)->MessageIter& = delete; - ~MessageIter() = default; + + // Non-movable + MessageIter(MessageIter&&) = delete; + fn operator=(MessageIter&&)->MessageIter& = delete; + + // Destructor + ~MessageIter() = default; /** * @brief Checks if the iterator is validly initialized. @@ -213,23 +258,51 @@ namespace dbus { * @brief RAII wrapper for DBusMessage. Automatically unrefs. */ class Message { - DBusMessage* m_msg = nullptr; + DBusMessage* m_msg = nullptr; ///< The D-Bus message object public: + /** + * @brief Constructor + * + * Initializes the D-Bus message object. + * + * @param msg The D-Bus message object to wrap + */ explicit Message(DBusMessage* msg = nullptr) : m_msg(msg) {} + /** + * @brief Destructor + * + * Frees the D-Bus message object if it was initialized. + */ ~Message() { if (m_msg) dbus_message_unref(m_msg); } + // Non-copyable Message(const Message&) = delete; fn operator=(const Message&)->Message& = delete; + /** + * @brief Move constructor + * + * Transfers ownership of the D-Bus message object. + * + * @param other The other Message object to move from + */ Message(Message&& other) noexcept : m_msg(std::exchange(other.m_msg, nullptr)) {} + /** + * @brief Move assignment operator + * + * Transfers ownership of the D-Bus message object. + * + * @param other The other Message object to move from + * @return A reference to this object + */ fn operator=(Message&& other) noexcept -> Message& { if (this != &other) { if (m_msg) @@ -285,7 +358,7 @@ namespace dbus { * @param path Object path (e.g., "/org/freedesktop/Notifications"). Must not be null. * @param interface Interface name (e.g., "org.freedesktop.Notifications"). Can be null. * @param method Method name (e.g., "Notify"). Must not be null. - * @return Result containing a MessageGuard on success, or DraconisError on failure. + * @return Result containing a MessageGuard on success, or DracError on failure. */ static fn newMethodCall(const char* destination, const char* path, const char* interface, const char* method) -> Result { @@ -298,6 +371,13 @@ namespace dbus { } private: + /** + * @brief Appends a single argument to the message. + * @tparam T Type of the argument to append. + * @param iter The D-Bus message iterator. + * @param arg The argument to append. + * @return True if the argument was appended successfully, false otherwise (e.g., allocation error). + */ template fn appendArgInternal(DBusMessageIter& iter, T&& arg) -> bool { using DecayedT = std::decay_t; @@ -313,26 +393,56 @@ namespace dbus { }; /** - * @brief RAII wrapper for DBusConnection. Automatically unrefs. + * @brief RAII wrapper for DBusConnection. Automatically unrefs the connection. + * + * This class provides a convenient way to manage the lifetime of a D-Bus connection. */ class Connection { - DBusConnection* m_conn = nullptr; + DBusConnection* m_conn = nullptr; ///< The D-Bus connection object public: + /** + * @brief Constructor + * + * Initializes the D-Bus connection object. + * + * @param conn The D-Bus connection object to wrap + */ explicit Connection(DBusConnection* conn = nullptr) : m_conn(conn) {} + /** + * @brief Destructor + * + * Frees the D-Bus connection object if it was initialized. + */ ~Connection() { if (m_conn) dbus_connection_unref(m_conn); } + // Non-copyable Connection(const Connection&) = delete; fn operator=(const Connection&)->Connection& = delete; + /** + * @brief Move constructor + * + * Transfers ownership of the D-Bus connection object. + * + * @param other The other Connection object to move from + */ Connection(Connection&& other) noexcept : m_conn(std::exchange(other.m_conn, nullptr)) {} + /** + * @brief Move assignment operator + * + * Transfers ownership of the D-Bus connection object. + * + * @param other The other Connection object to move from + * @return A reference to this object + */ fn operator=(Connection&& other) noexcept -> Connection& { if (this != &other) { if (m_conn) @@ -355,7 +465,7 @@ namespace dbus { * @brief Sends a message and waits for a reply, blocking execution. * @param message The D-Bus message guard to send. * @param timeout_milliseconds Timeout duration in milliseconds. - * @return Result containing the reply MessageGuard on success, or DraconisError on failure. + * @return Result containing the reply MessageGuard on success, or DracError on failure. */ [[nodiscard]] fn sendWithReplyAndBlock(const Message& message, const i32 timeout_milliseconds = 1000) const -> Result { @@ -371,16 +481,16 @@ namespace dbus { if (err.isSet()) { if (const char* errName = err.name()) { if (strcmp(errName, DBUS_ERROR_TIMEOUT) == 0 || strcmp(errName, DBUS_ERROR_NO_REPLY) == 0) - return Err(err.toDraconisError(DracErrorCode::Timeout)); + return Err(err.toDracError(DracErrorCode::Timeout)); if (strcmp(errName, DBUS_ERROR_SERVICE_UNKNOWN) == 0) - return Err(err.toDraconisError(DracErrorCode::NotFound)); + return Err(err.toDracError(DracErrorCode::NotFound)); if (strcmp(errName, DBUS_ERROR_ACCESS_DENIED) == 0) - return Err(err.toDraconisError(DracErrorCode::PermissionDenied)); + return Err(err.toDracError(DracErrorCode::PermissionDenied)); } - return Err(err.toDraconisError(DracErrorCode::PlatformSpecific)); + return Err(err.toDracError(DracErrorCode::PlatformSpecific)); } if (!rawReply) @@ -396,14 +506,14 @@ namespace dbus { /** * @brief Connects to a D-Bus bus type (Session or System). * @param bus_type The type of bus (DBUS_BUS_SESSION or DBUS_BUS_SYSTEM). - * @return Result containing a ConnectionGuard on success, or DraconisError on failure. + * @return Result containing a ConnectionGuard on success, or DracError on failure. */ static fn busGet(const DBusBusType bus_type) -> Result { Error err; DBusConnection* rawConn = dbus_bus_get(bus_type, err.get()); if (err.isSet()) - return Err(err.toDraconisError(DracErrorCode::ApiUnavailable)); + return Err(err.toDracError(DracErrorCode::ApiUnavailable)); if (!rawConn) return Err(DracError(DracErrorCode::ApiUnavailable, "dbus_bus_get returned null without setting error")); @@ -411,6 +521,6 @@ namespace dbus { return Connection(rawConn); } }; -} // namespace dbus +} // namespace DBus #endif // __linux__ || __FreeBSD__ || __DragonFly__ || __NetBSD__ diff --git a/src/Wrappers/Wayland.hpp b/src/Wrappers/Wayland.hpp index e91df18..fd09b93 100644 --- a/src/Wrappers/Wayland.hpp +++ b/src/Wrappers/Wayland.hpp @@ -10,34 +10,66 @@ #include "Util/Types.hpp" // clang-format on -struct wl_display; +namespace Wayland { + using util::types::i32, util::types::CStr, util::types::None; -namespace wl { - using display = wl_display; + using Display = wl_display; - inline fn Connect(const char* name) -> display* { + /** + * @brief Connect to a Wayland display + * + * This function establishes a connection to a Wayland display. It takes a + * display name as an argument. + * + * @param name The name of the display to connect to (or nullptr for default) + * @return A pointer to the Wayland display object + */ + inline fn Connect(CStr name) -> Display* { return wl_display_connect(name); } - inline fn Disconnect(display* display) -> void { + + /** + * @brief Disconnect from a Wayland display + * + * This function disconnects from a Wayland display. + * + * @param display The Wayland display object to disconnect from + * @return void + */ + inline fn Disconnect(Display* display) -> void { wl_display_disconnect(display); } - inline fn GetFd(display* display) -> int { + + /** + * @brief Get the file descriptor for a Wayland display + * + * This function retrieves the file descriptor for a Wayland display. + * + * @param display The Wayland display object + * @return The file descriptor for the Wayland display + */ + inline fn GetFd(Display* display) -> i32 { return wl_display_get_fd(display); } /** - * RAII wrapper for Wayland display connections - * Automatically handles resource acquisition and cleanup + * @brief RAII wrapper for Wayland display connections + * + * This class manages the connection to a Wayland display. It automatically + * handles resource acquisition and cleanup. */ class DisplayGuard { - display* m_display; + Display* m_display; ///< The Wayland display object public: /** - * Opens a Wayland display connection + * @brief Constructor + * + * This constructor sets up a custom logging handler for Wayland and + * establishes a connection to the Wayland display. */ DisplayGuard() { - wl_log_set_handler_client([](const char* fmt, va_list args) -> void { + wl_log_set_handler_client([](CStr fmt, va_list args) -> void { using util::types::i32, util::types::StringView; va_list argsCopy; @@ -71,6 +103,11 @@ namespace wl { m_display = Connect(nullptr); } + /** + * @brief Destructor + * + * This destructor disconnects from the Wayland display if it is valid. + */ ~DisplayGuard() { if (m_display) Disconnect(m_display); @@ -83,6 +120,15 @@ namespace wl { // Movable DisplayGuard(DisplayGuard&& other) noexcept : m_display(std::exchange(other.m_display, nullptr)) {} + + /** + * @brief Move assignment operator + * + * This operator transfers ownership of the Wayland display connection. + * + * @param other The other DisplayGuard object to move from + * @return A reference to this object + */ fn operator=(DisplayGuard&& other) noexcept -> DisplayGuard& { if (this != &other) { if (m_display) @@ -94,17 +140,40 @@ namespace wl { return *this; } + /** + * @brief Check if the display guard is valid + * + * This function checks if the display guard is valid (i.e., if it holds a + * valid Wayland display connection). + * + * @return True if the display guard is valid, false otherwise + */ [[nodiscard]] explicit operator bool() const { return m_display != nullptr; } - [[nodiscard]] fn get() const -> display* { + /** + * @brief Get the Wayland display connection + * + * This function retrieves the underlying Wayland display connection. + * + * @return The Wayland display connection + */ + [[nodiscard]] fn get() const -> Display* { return m_display; } - [[nodiscard]] fn fd() const -> util::types::i32 { + + /** + * @brief Get the file descriptor for the Wayland display + * + * This function retrieves the file descriptor for the Wayland display. + * + * @return The file descriptor for the Wayland display + */ + [[nodiscard]] fn fd() const -> i32 { return GetFd(m_display); } }; -} // namespace wl +} // namespace Wayland #endif // __linux__ || __FreeBSD__ || __DragonFly__ || __NetBSD__ diff --git a/src/Wrappers/XCB.hpp b/src/Wrappers/XCB.hpp index b6e16e1..418f325 100644 --- a/src/Wrappers/XCB.hpp +++ b/src/Wrappers/XCB.hpp @@ -9,22 +9,22 @@ #include "Util/Types.hpp" // clang-format on -namespace xcb { - using util::types::u8, util::types::i32, util::types::CStr, util::types::None; +namespace XCB { + using util::types::u8, util::types::u16, util::types::i32, util::types::u32, util::types::CStr, util::types::None; - using connection_t = xcb_connection_t; - using setup_t = xcb_setup_t; - using screen_t = xcb_screen_t; - using window_t = xcb_window_t; - using atom_t = xcb_atom_t; + using Connection = xcb_connection_t; + using Setup = xcb_setup_t; + using Screen = xcb_screen_t; + using Window = xcb_window_t; + using Atom = xcb_atom_t; - using generic_error_t = xcb_generic_error_t; - using intern_atom_cookie_t = xcb_intern_atom_cookie_t; - using intern_atom_reply_t = xcb_intern_atom_reply_t; - using get_property_cookie_t = xcb_get_property_cookie_t; - using get_property_reply_t = xcb_get_property_reply_t; + using GenericError = xcb_generic_error_t; + using IntAtomCookie = xcb_intern_atom_cookie_t; + using IntAtomReply = xcb_intern_atom_reply_t; + using GetPropCookie = xcb_get_property_cookie_t; + using GetPropReply = xcb_get_property_reply_t; - constexpr atom_t ATOM_WINDOW = XCB_ATOM_WINDOW; ///< Window atom + constexpr Atom ATOM_WINDOW = XCB_ATOM_WINDOW; ///< Window atom /** * @brief Enum representing different types of connection errors @@ -54,7 +54,7 @@ namespace xcb { * @param screenp Pointer to an integer that will store the screen number * @return A pointer to the connection object */ - inline fn Connect(const char* displayname, int* screenp) -> connection_t* { + inline fn Connect(CStr displayname, i32* screenp) -> Connection* { return xcb_connect(displayname, screenp); } @@ -66,7 +66,7 @@ namespace xcb { * * @param conn The connection object to disconnect from */ - inline fn Disconnect(connection_t* conn) -> void { + inline fn Disconnect(Connection* conn) -> void { xcb_disconnect(conn); } @@ -79,7 +79,7 @@ namespace xcb { * @param conn The connection object to check * @return 1 if the connection has an error, 0 otherwise */ - inline fn ConnectionHasError(connection_t* conn) -> int { + inline fn ConnectionHasError(Connection* conn) -> i32 { return xcb_connection_has_error(conn); } @@ -94,8 +94,7 @@ namespace xcb { * @param name The name of the atom * @return The cookie for the atom */ - inline fn InternAtom(connection_t* conn, const uint8_t only_if_exists, const uint16_t name_len, const char* name) - -> intern_atom_cookie_t { + inline fn InternAtom(Connection* conn, const u8 only_if_exists, const u16 name_len, CStr name) -> IntAtomCookie { return xcb_intern_atom(conn, only_if_exists, name_len, name); } @@ -110,8 +109,7 @@ namespace xcb { * @param err The pointer to the generic error * @return The reply for the atom */ - inline fn InternAtomReply(connection_t* conn, const intern_atom_cookie_t cookie, generic_error_t** err) - -> intern_atom_reply_t* { + inline fn InternAtomReply(Connection* conn, const IntAtomCookie cookie, GenericError** err) -> IntAtomReply* { return xcb_intern_atom_reply(conn, cookie, err); } @@ -128,14 +126,14 @@ namespace xcb { * @param type The type */ inline fn GetProperty( - connection_t* conn, - const uint8_t _delete, - const window_t window, - const atom_t property, - const atom_t type, - const uint32_t long_offset, - const uint32_t long_length - ) -> get_property_cookie_t { + Connection* conn, + const u8 _delete, + const Window window, + const Atom property, + const Atom type, + const u32 long_offset, + const u32 long_length + ) -> GetPropCookie { return xcb_get_property(conn, _delete, window, property, type, long_offset, long_length); } @@ -150,8 +148,7 @@ namespace xcb { * @param err The pointer to the generic error * @return The reply for the property */ - inline fn GetPropertyReply(connection_t* conn, const get_property_cookie_t cookie, generic_error_t** err) - -> get_property_reply_t* { + inline fn GetPropertyReply(Connection* conn, const GetPropCookie cookie, GenericError** err) -> GetPropReply* { return xcb_get_property_reply(conn, cookie, err); } @@ -161,7 +158,7 @@ namespace xcb { * @param reply The reply for the property * @return The value length for the property */ - inline fn GetPropertyValueLength(const get_property_reply_t* reply) -> int { + inline fn GetPropertyValueLength(const GetPropReply* reply) -> i32 { return xcb_get_property_value_length(reply); } @@ -171,7 +168,7 @@ namespace xcb { * @param reply The reply for the property * @return The value for the property */ - inline fn GetPropertyValue(const get_property_reply_t* reply) -> void* { + inline fn GetPropertyValue(const GetPropReply* reply) -> void* { return xcb_get_property_value(reply); } @@ -180,15 +177,16 @@ namespace xcb { * Automatically handles resource acquisition and cleanup */ class DisplayGuard { - connection_t* m_connection = nullptr; ///< The connection to the display + Connection* m_connection = nullptr; ///< The connection to the display public: /** * Opens an XCB connection * @param name Display name (nullptr for default) */ - explicit DisplayGuard(const util::types::CStr name = nullptr) + explicit DisplayGuard(const CStr name = nullptr) : m_connection(Connect(name, nullptr)) {} + ~DisplayGuard() { if (m_connection) Disconnect(m_connection); @@ -229,7 +227,7 @@ namespace xcb { * @brief Get the connection to the display * @return The connection to the display */ - [[nodiscard]] fn get() const -> connection_t* { + [[nodiscard]] fn get() const -> Connection* { return m_connection; } @@ -237,7 +235,7 @@ namespace xcb { * @brief Get the setup for the display * @return The setup for the display */ - [[nodiscard]] fn setup() const -> const setup_t* { + [[nodiscard]] fn setup() const -> const Setup* { return m_connection ? xcb_get_setup(m_connection) : nullptr; } @@ -245,8 +243,9 @@ namespace xcb { * @brief Get the root screen for the display * @return The root screen for the display */ - [[nodiscard]] fn rootScreen() const -> screen_t* { - const setup_t* setup = this->setup(); + [[nodiscard]] fn rootScreen() const -> Screen* { + const Setup* setup = this->setup(); + return setup ? xcb_setup_roots_iterator(setup).data : nullptr; } }; @@ -335,6 +334,6 @@ namespace xcb { return *m_reply; } }; -} // namespace xcb +} // namespace XCB #endif // __linux__ || __FreeBSD__ || __DragonFly__ || __NetBSD__ diff --git a/src/main.cpp b/src/main.cpp index 09e3f4a..e5d234a 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -10,9 +10,12 @@ #include // std::cout #endif -#include "Config/Config.hpp" #include "Core/SystemData.hpp" + +#include "Config/Config.hpp" + #include "UI/UI.hpp" + #include "Util/Definitions.hpp" #include "Util/Logging.hpp" #include "Util/Types.hpp"